mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Add JavaFXWebcam window
This commit is contained in:
parent
fa208157cc
commit
5dec138b4f
@ -49,7 +49,7 @@ import javafx.beans.value.ChangeListener;
|
||||
import javafx.event.EventHandler;
|
||||
|
||||
@FxmlView
|
||||
public class AccountView extends ActivatableView<TabPane, AccountViewModel> {
|
||||
public class AccountView extends ActivatableView<TabPane, Void> {
|
||||
|
||||
@FXML
|
||||
Tab accountSettingsTab;
|
||||
@ -67,8 +67,8 @@ public class AccountView extends ActivatableView<TabPane, AccountViewModel> {
|
||||
private EventHandler<KeyEvent> keyEventEventHandler;
|
||||
|
||||
@Inject
|
||||
private AccountView(AccountViewModel model, CachingViewLoader viewLoader, Navigation navigation) {
|
||||
super(model);
|
||||
private AccountView(CachingViewLoader viewLoader, Navigation navigation) {
|
||||
super();
|
||||
this.viewLoader = viewLoader;
|
||||
this.navigation = navigation;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ package bisq.desktop.main.account.content.notifications;
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.WebCamWindow;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
@ -55,6 +56,8 @@ public class NotificationsView extends ActivatableView<GridPane, Void> {
|
||||
private Button wipeOutButton;
|
||||
private Button devButton;
|
||||
private ChangeListener<Boolean> useSoundCheckBoxListener, tradeCheckBoxListener;
|
||||
private WebCamWindow webCamWindow;
|
||||
private QrCodeReader qrCodeReader;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
@ -74,12 +77,26 @@ public class NotificationsView extends ActivatableView<GridPane, Void> {
|
||||
@Override
|
||||
public void initialize() {
|
||||
FormBuilder.addTitledGroupBg(root, gridRow, 4, Res.get("account.notifications.setup.title"));
|
||||
webCamButton = FormBuilder.addLabelButton(root, gridRow, Res.get("account.notifications.webcam.label"), Res.get("account.notifications.webcam.title"), Layout.FIRST_ROW_DISTANCE).second;
|
||||
webCamButton = FormBuilder.addLabelButton(root, gridRow, Res.get("account.notifications.webcam.label"),
|
||||
Res.get("account.notifications.webcam.title"), Layout.FIRST_ROW_DISTANCE).second;
|
||||
webCamButton.setDefaultButton(true);
|
||||
|
||||
webCamButton.setOnAction((event) -> {
|
||||
webCamButton.setDisable(true);
|
||||
new QrCodeWindow(this::applyKeyAndToken);
|
||||
new WebCamLauncher(webCam -> {
|
||||
webCamWindow = new WebCamWindow(webCam.getViewSize().width, webCam.getViewSize().height)
|
||||
.onClose(() -> {
|
||||
webCamButton.setDisable(false);
|
||||
qrCodeReader.close();
|
||||
});
|
||||
webCamWindow.show();
|
||||
|
||||
qrCodeReader = new QrCodeReader(webCam, webCamWindow.getImageView(), qrCode -> {
|
||||
webCamWindow.hide();
|
||||
webCamButton.setDisable(false);
|
||||
tokenInputTextField.setText(qrCode);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tokenInputTextField = FormBuilder.addLabelInputTextField(root, ++gridRow, Res.get("account.notifications.email.label")).second;
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.account.content.notifications;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.image.WritableImage;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
|
||||
import com.github.sarxos.webcam.Webcam;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import javafx.embed.swing.SwingFXUtils;
|
||||
|
||||
@Slf4j
|
||||
// Must not be UI thread
|
||||
public class QrCodeReader extends Thread {
|
||||
private Webcam webCam;
|
||||
private ImageView imageView;
|
||||
private Consumer<String> resultHandler;
|
||||
private boolean isRunning;
|
||||
|
||||
public QrCodeReader(Webcam webCam, ImageView imageView, Consumer<String> resultHandler) {
|
||||
this.webCam = webCam;
|
||||
this.imageView = imageView;
|
||||
this.resultHandler = resultHandler;
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!webCam.isOpen())
|
||||
webCam.open();
|
||||
|
||||
isRunning = true;
|
||||
Result result;
|
||||
BufferedImage bufferedImage;
|
||||
while (isRunning) {
|
||||
bufferedImage = webCam.getImage();
|
||||
if (bufferedImage != null) {
|
||||
WritableImage writableImage = SwingFXUtils.toFXImage(bufferedImage, null);
|
||||
imageView.setImage(writableImage);
|
||||
|
||||
LuminanceSource source = new BufferedImageLuminanceSource(bufferedImage);
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
|
||||
try {
|
||||
result = new MultiFormatReader().decode(bitmap);
|
||||
isRunning = false;
|
||||
String qrCode = result.getText();
|
||||
UserThread.execute(() -> resultHandler.accept(qrCode));
|
||||
} catch (NotFoundException ignore) {
|
||||
// No qr code in image...
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
log.error(t.toString());
|
||||
} finally {
|
||||
webCam.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
isRunning = false;
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
package bisq.desktop.main.account.content.notifications;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.FlowLayout;
|
||||
import java.awt.event.WindowEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
|
||||
|
||||
import com.github.sarxos.webcam.Webcam;
|
||||
import com.github.sarxos.webcam.WebcamPanel;
|
||||
import com.google.zxing.BinaryBitmap;
|
||||
import com.google.zxing.LuminanceSource;
|
||||
import com.google.zxing.MultiFormatReader;
|
||||
import com.google.zxing.NotFoundException;
|
||||
import com.google.zxing.Result;
|
||||
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
|
||||
import com.google.zxing.common.HybridBinarizer;
|
||||
import javax.swing.JFrame;
|
||||
|
||||
public class QrCodeWindow extends JFrame {
|
||||
|
||||
private Webcam webcam;
|
||||
private Executor executor = Utilities.getListeningSingleThreadExecutor("readQR-runner");
|
||||
|
||||
private WebcamPanel panel;
|
||||
private Consumer<String> qrCodeResultHandler;
|
||||
|
||||
public QrCodeWindow(Consumer<String> qrCodeResultHandler) {
|
||||
this.qrCodeResultHandler = qrCodeResultHandler;
|
||||
|
||||
setLayout(new FlowLayout());
|
||||
setTitle("Bisq Notification token"); //TODO
|
||||
|
||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||
|
||||
addWindowListener(new java.awt.event.WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing(WindowEvent windowEvent) {
|
||||
webcam.close();
|
||||
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
|
||||
}
|
||||
});
|
||||
|
||||
executor.execute(this::doRun);
|
||||
}
|
||||
|
||||
private void doRun() {
|
||||
try {
|
||||
webcam = Webcam.getDefault(1000); // one second timeout - the default is too long
|
||||
Dimension[] sizes = webcam.getViewSizes();
|
||||
webcam.setViewSize(sizes[sizes.length - 1]);
|
||||
panel = new WebcamPanel(webcam);
|
||||
add(panel);
|
||||
pack();
|
||||
setLocationRelativeTo(null);
|
||||
setVisible(true);
|
||||
} catch (TimeoutException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// check 10 times a second for the QR code
|
||||
boolean run = true;
|
||||
while (run) {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
Result result = null;
|
||||
BufferedImage image;
|
||||
|
||||
if (webcam != null && webcam.isOpen()) {
|
||||
if ((image = webcam.getImage()) == null)
|
||||
continue;
|
||||
|
||||
LuminanceSource source = new BufferedImageLuminanceSource(image);
|
||||
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
|
||||
|
||||
try {
|
||||
result = new MultiFormatReader().decode(bitmap);
|
||||
} catch (NotFoundException ignore) {
|
||||
// fall thru, it means there is no QR code in image
|
||||
}
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
String qrCode = result.getText();
|
||||
//boolean sendConfirmation = phone.validatePhoneId(qrCode);
|
||||
// phone.save();
|
||||
dispatchEvent(new WindowEvent(this, WindowEvent.WINDOW_CLOSING));
|
||||
run = false;
|
||||
UserThread.execute(() -> {
|
||||
qrCodeResultHandler.accept(qrCode);
|
||||
});
|
||||
/* Platform.runLater(
|
||||
() -> {
|
||||
// app.updateGUI();
|
||||
// app.sendConfirmation();
|
||||
}
|
||||
);*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.account.content.notifications;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
|
||||
import java.awt.Dimension;
|
||||
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
|
||||
import com.github.sarxos.webcam.Webcam;
|
||||
|
||||
@Slf4j
|
||||
// Must not be UI thread
|
||||
public class WebCamLauncher extends Thread {
|
||||
private Consumer<Webcam> resultHandler;
|
||||
|
||||
public WebCamLauncher(Consumer<Webcam> resultHandler) {
|
||||
this.resultHandler = resultHandler;
|
||||
|
||||
start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Webcam webCam = Webcam.getDefault(1000); // one second timeout - the default is too long
|
||||
Dimension[] sizes = webCam.getViewSizes();
|
||||
Dimension size = sizes[sizes.length - 1]; // the largest size
|
||||
webCam.setViewSize(size);
|
||||
UserThread.execute(() -> resultHandler.accept(webCam));
|
||||
} catch (TimeoutException e) {
|
||||
log.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@
|
||||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<AnchorPane fx:id="root" prefHeight="660.0" prefWidth="1000.0" xmlns="http://javafx.com/javafx/8"
|
||||
xmlns:fx="http://javafx.com/fxml/1"
|
||||
xmlns:fx="http://javafx.com/fxml"
|
||||
fx:controller="bisq.desktop.main.account.settings.AccountSettingsView">
|
||||
|
||||
<VBox fx:id="leftVBox" prefWidth="240" spacing="5" AnchorPane.bottomAnchor="20" AnchorPane.leftAnchor="15"
|
||||
|
@ -0,0 +1,75 @@
|
||||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or (at
|
||||
* your option) any later version.
|
||||
*
|
||||
* Bisq is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
|
||||
* License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.overlays.windows;
|
||||
|
||||
|
||||
import bisq.desktop.main.overlays.Overlay;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.image.ImageView;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Pos;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class WebCamWindow extends Overlay<WebCamWindow> {
|
||||
|
||||
@Getter
|
||||
private ImageView imageView = new ImageView();
|
||||
|
||||
|
||||
public WebCamWindow(double width, double height) {
|
||||
type = Type.Feedback;
|
||||
|
||||
imageView.setFitWidth(width);
|
||||
imageView.setFitHeight(height);
|
||||
}
|
||||
|
||||
public void show() {
|
||||
headLine = Res.get("account.notifications.webCamWindow.headline");
|
||||
|
||||
createGridPane();
|
||||
addHeadLine();
|
||||
addSeparator();
|
||||
addContent();
|
||||
addCloseButton();
|
||||
applyStyles();
|
||||
display();
|
||||
|
||||
}
|
||||
|
||||
private void addContent() {
|
||||
GridPane.setHalignment(headLineLabel, HPos.CENTER);
|
||||
|
||||
Label label = FormBuilder.addLabel(gridPane, ++rowIndex, Res.get("account.notifications.waitingForWebCam"));
|
||||
label.setAlignment(Pos.CENTER);
|
||||
GridPane.setColumnSpan(label, 2);
|
||||
GridPane.setHalignment(label, HPos.CENTER);
|
||||
|
||||
GridPane.setRowIndex(imageView, rowIndex);
|
||||
GridPane.setColumnSpan(imageView, 2);
|
||||
gridPane.getChildren().add(imageView);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user