diff --git a/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewCell.java b/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewCell.java new file mode 100644 index 0000000..47785da --- /dev/null +++ b/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewCell.java @@ -0,0 +1,64 @@ +package de.vanitasvitae.omemoqrgenerator; + +import java.io.IOException; + +import com.jfoenix.controls.JFXListCell; +import com.jfoenix.controls.JFXToggleButton; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.control.Label; +import javafx.scene.layout.HBox; + +public class ListViewCell extends JFXListCell { + + @FXML + private HBox hBox; + + @FXML + private Label id; + + @FXML + private Label fingerprint; + + @FXML + private JFXToggleButton toggle; + + private QrDisplayController displayController = null; + + public ListViewCell() { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/fxml/item.fxml")); + fxmlLoader.setController(this); + try + { + fxmlLoader.load(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public void setDisplayController(QrDisplayController controller) { + this.displayController = controller; + } + + @Override + public void updateItem(OmemoIdentity identity, boolean empty) { + if (empty) { + return; + } + + if (id != null) id.setText(Integer.toString(identity.getDevice().getDeviceId())); + if (fingerprint != null) fingerprint.setText(identity.getFingerprint().blocksOf8Chars()); + if (toggle != null) toggle.setSelected(identity.getEnabled()); + if (hBox != null) setGraphic(hBox); + if (toggle != null) { + toggle.setOnAction(actionEvent -> { + identity.setEnabled(toggle.isSelected()); + if (displayController != null) { + displayController.drawQRCode(); + } + }); + } + } +} diff --git a/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewController.java b/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewController.java new file mode 100644 index 0000000..704f653 --- /dev/null +++ b/src/main/java/de/vanitasvitae/omemoqrgenerator/ListViewController.java @@ -0,0 +1,37 @@ +package de.vanitasvitae.omemoqrgenerator; + +import java.util.Collection; + +import com.jfoenix.controls.JFXListView; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; + +public class ListViewController { + + @FXML + private JFXListView listView; + + private ObservableList identities = FXCollections.observableArrayList(); + + private QrDisplayController displayController = null; + + public void setDisplayController(QrDisplayController controller) { + this.displayController = controller; + } + + public void setIdentities(Collection identities) { + this.identities.clear(); + this.identities.addAll(identities); + } + + @FXML + void initialize() { + listView.setCellFactory(listView -> { + ListViewCell cell = new ListViewCell(); + cell.setDisplayController(displayController); + return new ListViewCell(); + }); + listView.setItems(identities); + } +} diff --git a/src/main/java/de/vanitasvitae/omemoqrgenerator/Main.java b/src/main/java/de/vanitasvitae/omemoqrgenerator/Main.java index a2b604a..d6b51e7 100644 --- a/src/main/java/de/vanitasvitae/omemoqrgenerator/Main.java +++ b/src/main/java/de/vanitasvitae/omemoqrgenerator/Main.java @@ -1,28 +1,34 @@ package de.vanitasvitae.omemoqrgenerator; -import java.util.Arrays; +import java.io.IOException; import java.util.Map; import org.jivesoftware.smack.SmackConfiguration; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.tcp.XMPPTCPConnection; -import org.jivesoftware.smackx.disco.ServiceDiscoveryManager; import org.jivesoftware.smackx.omemo.internal.OmemoDevice; import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint; -import org.jivesoftware.smackx.pubsub.PubSubManager; import javafx.application.Application; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; import org.jxmpp.jid.BareJid; +import org.jxmpp.stringprep.XmppStringprepException; public class Main extends Application implements LoginCallback { private Stage stage; - + /* + * Trim down Smack. + */ static { SmackConfiguration.DEBUG = true; SmackConfiguration.addDisabledSmackClasses("org.jivesoftware.smack.ReconnectionManager", @@ -58,13 +64,18 @@ public class Main extends Application implements LoginCallback { "org.jivesoftware.smackx.iqlast", "org.jivesoftware.smackx.receipts", "org.jivesoftware.smackx.iqversion" - ); + ); } public static void main(String[] args) { launch(args); } + /** + * Render the login screen. + * @param stage stage + * @throws Exception in case something goes wrong. + */ @Override public void start(Stage stage) throws Exception { this.stage = stage; @@ -73,6 +84,8 @@ public class Main extends Application implements LoginCallback { Parent root = loader.load(); stage.setMinHeight(600); stage.setMinWidth(400); + + // Register ourselves as callback for the login button. LoginController loginController = loader.getController(); loginController.setLoginCallback(this); @@ -84,32 +97,37 @@ public class Main extends Application implements LoginCallback { @Override public void login(String username, String password) { + XMPPTCPConnection connection = null; try { - XMPPTCPConnection connection = new XMPPTCPConnection(username, password); + connection = new XMPPTCPConnection(username, password); connection.connect().login(); + if (connection == null) { + return; + } + BareJid jid = connection.getUser().asBareJid(); Map fingerprints = Util.getFingerprints(connection); + ObservableList identities = FXCollections.observableArrayList(); + for (OmemoDevice device : fingerprints.keySet()) { + identities.addAll(new OmemoIdentity(device, fingerprints.get(device))); + } + connection.disconnect(new Presence(Presence.Type.unavailable)); FXMLLoader loader = new FXMLLoader(); loader.setLocation(getClass().getResource("/fxml/qrdisplay.fxml")); Parent root = loader.load(); QrDisplayController controller = loader.getController(); - controller.setFingerprints(jid, fingerprints); + controller.setFingerprints(jid, identities); Scene scene = new Scene(root, 400, 600); stage.setTitle("OMEMO QR-Code Generator"); stage.setScene(scene); stage.show(); - } catch (Exception e) { e.printStackTrace(); } } - - - - } diff --git a/src/main/java/de/vanitasvitae/omemoqrgenerator/OmemoIdentity.java b/src/main/java/de/vanitasvitae/omemoqrgenerator/OmemoIdentity.java new file mode 100644 index 0000000..9e01b80 --- /dev/null +++ b/src/main/java/de/vanitasvitae/omemoqrgenerator/OmemoIdentity.java @@ -0,0 +1,33 @@ +package de.vanitasvitae.omemoqrgenerator; + +import org.jivesoftware.smackx.omemo.internal.OmemoDevice; +import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint; + +public class OmemoIdentity { + + private final OmemoDevice device; + private final OmemoFingerprint fingerprint; + private boolean enabled; + + public OmemoIdentity(OmemoDevice device, OmemoFingerprint fingerprint) { + this.device = device; + this.fingerprint = fingerprint; + this.enabled = true; + } + + public OmemoDevice getDevice() { + return device; + } + + public OmemoFingerprint getFingerprint() { + return fingerprint; + } + + public boolean getEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } +} diff --git a/src/main/java/de/vanitasvitae/omemoqrgenerator/QrDisplayController.java b/src/main/java/de/vanitasvitae/omemoqrgenerator/QrDisplayController.java index 2df08a3..f6407e8 100644 --- a/src/main/java/de/vanitasvitae/omemoqrgenerator/QrDisplayController.java +++ b/src/main/java/de/vanitasvitae/omemoqrgenerator/QrDisplayController.java @@ -2,8 +2,10 @@ package de.vanitasvitae.omemoqrgenerator; import java.awt.*; import java.awt.image.BufferedImage; +import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.Set; import org.jivesoftware.smackx.omemo.internal.OmemoDevice; import org.jivesoftware.smackx.omemo.trust.OmemoFingerprint; @@ -12,10 +14,11 @@ import com.google.zxing.BarcodeFormat; import com.google.zxing.WriterException; import com.google.zxing.common.BitMatrix; import com.google.zxing.qrcode.QRCodeWriter; -import com.jfoenix.controls.JFXTextArea; +import javafx.collections.ObservableList; import javafx.embed.swing.SwingFXUtils; import javafx.fxml.FXML; import javafx.scene.image.ImageView; +import javafx.scene.layout.GridPane; import org.jxmpp.jid.BareJid; public class QrDisplayController { @@ -24,36 +27,45 @@ public class QrDisplayController { private ImageView qr_view; @FXML - private JFXTextArea content_text; + private GridPane listView; + + @FXML + private ListViewController listViewController; private BareJid jid; - private Map fingerprintMap; + private ObservableList identities = null; - public void setFingerprints(BareJid jid, Map fingerprints) { + public void setFingerprints(BareJid jid, ObservableList identities) { this.jid = jid; - this.fingerprintMap = fingerprints; - drawQRCode(jid, fingerprints); + this.identities = identities; + this.listViewController.setDisplayController(this); + this.listViewController.setIdentities(this.identities); + drawQRCode(); } - public void drawQRCode(BareJid jid, Map fingerprints) { + public void drawQRCode() { int width = 300, height = 300; QRCodeWriter qrCodeWriter = new QRCodeWriter(); String content = "xmpp:" + jid.toString(); - Iterator iterator = fingerprints.keySet().iterator(); - if (iterator.hasNext()) { - OmemoDevice first = iterator.next(); - content += "?omemo-sid-" + first.getDeviceId() + "=" + fingerprints.get(first); + Iterator iterator = identities.iterator(); + + while (iterator.hasNext()) { + OmemoIdentity first = iterator.next(); + if (first.getEnabled()) { + content += "?omemo-sid-" + first.getDevice().getDeviceId() + "=" + first.getFingerprint().toString(); + break; + } } while (iterator.hasNext()) { - OmemoDevice next = iterator.next(); - content += ";omemo-sid-" + next.getDeviceId() + "=" + fingerprints.get(next); + OmemoIdentity next = iterator.next(); + if (next.getEnabled()) { + content += ";omemo-sid-" + next.getDevice().getDeviceId() + "=" + next.getFingerprint().toString(); + } } - content_text.setText(content); - BufferedImage image; try { diff --git a/src/main/resources/fxml/item.fxml b/src/main/resources/fxml/item.fxml new file mode 100644 index 0000000..ea9d1c6 --- /dev/null +++ b/src/main/resources/fxml/item.fxml @@ -0,0 +1,13 @@ + + + + + + + + + + diff --git a/src/main/resources/fxml/listview.fxml b/src/main/resources/fxml/listview.fxml new file mode 100644 index 0000000..ca6b40b --- /dev/null +++ b/src/main/resources/fxml/listview.fxml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/main/resources/fxml/login.fxml b/src/main/resources/fxml/login.fxml index 28b304b..a418cee 100644 --- a/src/main/resources/fxml/login.fxml +++ b/src/main/resources/fxml/login.fxml @@ -7,7 +7,11 @@ - + diff --git a/src/main/resources/fxml/qrdisplay.fxml b/src/main/resources/fxml/qrdisplay.fxml index fca4093..5890d7c 100644 --- a/src/main/resources/fxml/qrdisplay.fxml +++ b/src/main/resources/fxml/qrdisplay.fxml @@ -2,14 +2,9 @@ - - - - - - +