mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-20 10:22:18 +01:00
Add priv. notifications
This commit is contained in:
parent
dc5cc522e2
commit
3e2f09b4a1
@ -57,7 +57,7 @@ public final class Alert implements StoragePayload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSigAndStoragePubKey(String signatureAsBase64, PublicKey storagePublicKey) {
|
public void setSigAndPubKey(String signatureAsBase64, PublicKey storagePublicKey) {
|
||||||
this.signatureAsBase64 = signatureAsBase64;
|
this.signatureAsBase64 = signatureAsBase64;
|
||||||
this.storagePublicKey = storagePublicKey;
|
this.storagePublicKey = storagePublicKey;
|
||||||
this.storagePublicKeyBytes = new X509EncodedKeySpec(this.storagePublicKey.getEncoded()).getEncoded();
|
this.storagePublicKeyBytes = new X509EncodedKeySpec(this.storagePublicKey.getEncoded()).getEncoded();
|
||||||
|
@ -125,7 +125,7 @@ public class AlertManager {
|
|||||||
private void signAndAddSignatureToAlertMessage(Alert alert) {
|
private void signAndAddSignatureToAlertMessage(Alert alert) {
|
||||||
String alertMessageAsHex = Utils.HEX.encode(alert.message.getBytes());
|
String alertMessageAsHex = Utils.HEX.encode(alert.message.getBytes());
|
||||||
String signatureAsBase64 = alertSigningKey.signMessage(alertMessageAsHex);
|
String signatureAsBase64 = alertSigningKey.signMessage(alertMessageAsHex);
|
||||||
alert.setSigAndStoragePubKey(signatureAsBase64, keyRing.getSignatureKeyPair().getPublic());
|
alert.setSigAndPubKey(signatureAsBase64, keyRing.getSignatureKeyPair().getPublic());
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean verifySignature(Alert alert) {
|
private boolean verifySignature(Alert alert) {
|
||||||
|
@ -34,5 +34,7 @@ public class AlertModule extends AppModule {
|
|||||||
protected final void configure() {
|
protected final void configure() {
|
||||||
bind(AlertManager.class).in(Singleton.class);
|
bind(AlertManager.class).in(Singleton.class);
|
||||||
bind(AlertService.class).in(Singleton.class);
|
bind(AlertService.class).in(Singleton.class);
|
||||||
|
bind(PrivateNotificationManager.class).in(Singleton.class);
|
||||||
|
bind(PrivateNotificationService.class).in(Singleton.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare 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.
|
||||||
|
*
|
||||||
|
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.alert;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
|
import io.bitsquare.common.crypto.Sig;
|
||||||
|
import io.bitsquare.common.wire.Payload;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
|
||||||
|
public final class PrivateNotification implements Payload {
|
||||||
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
|
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PrivateNotification.class);
|
||||||
|
|
||||||
|
public final String message;
|
||||||
|
private String signatureAsBase64;
|
||||||
|
private transient PublicKey publicKey;
|
||||||
|
private byte[] publicKeyBytes;
|
||||||
|
|
||||||
|
public PrivateNotification(String message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
|
||||||
|
try {
|
||||||
|
in.defaultReadObject();
|
||||||
|
publicKey = KeyFactory.getInstance(Sig.KEY_ALGO, "BC").generatePublic(new X509EncodedKeySpec(publicKeyBytes));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
log.warn("Exception at readObject: " + t.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSigAndPubKey(String signatureAsBase64, PublicKey storagePublicKey) {
|
||||||
|
this.signatureAsBase64 = signatureAsBase64;
|
||||||
|
this.publicKey = storagePublicKey;
|
||||||
|
this.publicKeyBytes = new X509EncodedKeySpec(this.publicKey.getEncoded()).getEncoded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSignatureAsBase64() {
|
||||||
|
return signatureAsBase64;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare 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.
|
||||||
|
*
|
||||||
|
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.alert;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import io.bitsquare.common.crypto.KeyRing;
|
||||||
|
import io.bitsquare.crypto.DecryptedMsgWithPubKey;
|
||||||
|
import io.bitsquare.p2p.Message;
|
||||||
|
import io.bitsquare.p2p.NodeAddress;
|
||||||
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import javafx.beans.property.ObjectProperty;
|
||||||
|
import javafx.beans.property.ReadOnlyObjectProperty;
|
||||||
|
import javafx.beans.property.SimpleObjectProperty;
|
||||||
|
import org.bitcoinj.core.ECKey;
|
||||||
|
import org.bitcoinj.core.Utils;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.security.SignatureException;
|
||||||
|
|
||||||
|
import static org.bitcoinj.core.Utils.HEX;
|
||||||
|
|
||||||
|
public class PrivateNotificationManager {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PrivateNotificationManager.class);
|
||||||
|
|
||||||
|
private final PrivateNotificationService privateNotificationService;
|
||||||
|
private final KeyRing keyRing;
|
||||||
|
private final ObjectProperty<PrivateNotification> privateNotificationMessageProperty = new SimpleObjectProperty<>();
|
||||||
|
|
||||||
|
// Pub key for developer global privateNotification message
|
||||||
|
private static final String pubKeyAsHex = "02ba7c5de295adfe57b60029f3637a2c6b1d0e969a8aaefb9e0ddc3a7963f26925";
|
||||||
|
private ECKey privateNotificationSigningKey;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, Initialization
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PrivateNotificationManager(PrivateNotificationService privateNotificationService, KeyRing keyRing) {
|
||||||
|
this.privateNotificationService = privateNotificationService;
|
||||||
|
this.keyRing = keyRing;
|
||||||
|
|
||||||
|
privateNotificationService.addDecryptedDirectMessageListener(this::handleMessage);
|
||||||
|
privateNotificationService.addDecryptedMailboxListener(this::handleMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleMessage(DecryptedMsgWithPubKey decryptedMsgWithPubKey, NodeAddress senderNodeAddress) {
|
||||||
|
Message message = decryptedMsgWithPubKey.message;
|
||||||
|
if (message instanceof PrivateNotificationMessage) {
|
||||||
|
PrivateNotificationMessage privateNotificationMessage = (PrivateNotificationMessage) message;
|
||||||
|
log.trace("Received privateNotificationMessage: " + privateNotificationMessage);
|
||||||
|
if (privateNotificationMessage.getSenderNodeAddress().equals(senderNodeAddress)) {
|
||||||
|
final PrivateNotification privateNotification = privateNotificationMessage.privateNotification;
|
||||||
|
if (verifySignature(privateNotification))
|
||||||
|
privateNotificationMessageProperty.set(privateNotification);
|
||||||
|
} else {
|
||||||
|
log.warn("Peer address not matching for privateNotificationMessage");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// API
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public ReadOnlyObjectProperty<PrivateNotification> privateNotificationProperty() {
|
||||||
|
return privateNotificationMessageProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean sendPrivateNotificationMessageIfKeyIsValid(PrivateNotification privateNotification, Offer offer, String privKeyString) {
|
||||||
|
// if there is a previous message we remove that first
|
||||||
|
// if (user.getDevelopersPrivateNotification() != null)
|
||||||
|
// removePrivateNotificationMessageIfKeyIsValid(privKeyString);
|
||||||
|
|
||||||
|
boolean isKeyValid = isKeyValid(privKeyString);
|
||||||
|
if (isKeyValid) {
|
||||||
|
signAndAddSignatureToPrivateNotificationMessage(privateNotification);
|
||||||
|
// user.setDevelopersPrivateNotification(privateNotification);
|
||||||
|
privateNotificationService.sendPrivateNotificationMessage(privateNotification, offer, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
return isKeyValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removePrivateNotificationMessageIfKeyIsValid(String privKeyString) {
|
||||||
|
/* PrivateNotification developersPrivateNotification = user.getDevelopersPrivateNotification();
|
||||||
|
if (isKeyValid(privKeyString) && developersPrivateNotification != null) {
|
||||||
|
privateNotificationService.removePrivateNotificationMessage(developersPrivateNotification, null, null);
|
||||||
|
user.setDevelopersPrivateNotification(null);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isKeyValid(String privKeyString) {
|
||||||
|
try {
|
||||||
|
privateNotificationSigningKey = ECKey.fromPrivate(new BigInteger(1, HEX.decode(privKeyString)));
|
||||||
|
return pubKeyAsHex.equals(Utils.HEX.encode(privateNotificationSigningKey.getPubKey()));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void signAndAddSignatureToPrivateNotificationMessage(PrivateNotification privateNotification) {
|
||||||
|
String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.message.getBytes());
|
||||||
|
String signatureAsBase64 = privateNotificationSigningKey.signMessage(privateNotificationMessageAsHex);
|
||||||
|
privateNotification.setSigAndPubKey(signatureAsBase64, keyRing.getSignatureKeyPair().getPublic());
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean verifySignature(PrivateNotification privateNotification) {
|
||||||
|
String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.message.getBytes());
|
||||||
|
try {
|
||||||
|
ECKey.fromPublicOnly(HEX.decode(pubKeyAsHex)).verifyMessage(privateNotificationMessageAsHex, privateNotification.getSignatureAsBase64());
|
||||||
|
return true;
|
||||||
|
} catch (SignatureException e) {
|
||||||
|
log.warn("verifySignature failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package io.bitsquare.alert;
|
||||||
|
|
||||||
|
import io.bitsquare.app.Version;
|
||||||
|
import io.bitsquare.p2p.NodeAddress;
|
||||||
|
import io.bitsquare.p2p.messaging.MailboxMessage;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class PrivateNotificationMessage implements MailboxMessage {
|
||||||
|
// That object is sent over the wire, so we need to take care of version compatibility.
|
||||||
|
private static final long serialVersionUID = Version.P2P_NETWORK_VERSION;
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PrivateNotificationMessage.class);
|
||||||
|
private NodeAddress myNodeAddress;
|
||||||
|
public PrivateNotification privateNotification;
|
||||||
|
private final String uid = UUID.randomUUID().toString();
|
||||||
|
private final int messageVersion = Version.getP2PMessageVersion();
|
||||||
|
|
||||||
|
public PrivateNotificationMessage(PrivateNotification privateNotification, NodeAddress myNodeAddress) {
|
||||||
|
this.myNodeAddress = myNodeAddress;
|
||||||
|
this.privateNotification = privateNotification;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NodeAddress getSenderNodeAddress() {
|
||||||
|
return myNodeAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUID() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMessageVersion() {
|
||||||
|
return messageVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof PrivateNotificationMessage)) return false;
|
||||||
|
|
||||||
|
PrivateNotificationMessage that = (PrivateNotificationMessage) o;
|
||||||
|
|
||||||
|
if (messageVersion != that.messageVersion) return false;
|
||||||
|
if (myNodeAddress != null ? !myNodeAddress.equals(that.myNodeAddress) : that.myNodeAddress != null)
|
||||||
|
return false;
|
||||||
|
if (privateNotification != null ? !privateNotification.equals(that.privateNotification) : that.privateNotification != null)
|
||||||
|
return false;
|
||||||
|
return !(uid != null ? !uid.equals(that.uid) : that.uid != null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = myNodeAddress != null ? myNodeAddress.hashCode() : 0;
|
||||||
|
result = 31 * result + (privateNotification != null ? privateNotification.hashCode() : 0);
|
||||||
|
result = 31 * result + (uid != null ? uid.hashCode() : 0);
|
||||||
|
result = 31 * result + messageVersion;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "PrivateNotificationMessage{" +
|
||||||
|
"myNodeAddress=" + myNodeAddress +
|
||||||
|
", privateNotification=" + privateNotification +
|
||||||
|
", uid='" + uid + '\'' +
|
||||||
|
", messageVersion=" + messageVersion +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare 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.
|
||||||
|
*
|
||||||
|
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.alert;
|
||||||
|
|
||||||
|
import io.bitsquare.common.handlers.ErrorMessageHandler;
|
||||||
|
import io.bitsquare.common.handlers.ResultHandler;
|
||||||
|
import io.bitsquare.p2p.P2PService;
|
||||||
|
import io.bitsquare.p2p.messaging.DecryptedDirectMessageListener;
|
||||||
|
import io.bitsquare.p2p.messaging.DecryptedMailboxListener;
|
||||||
|
import io.bitsquare.p2p.messaging.SendMailboxMessageListener;
|
||||||
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to load global privateNotification messages.
|
||||||
|
* The message is signed by the project developers private key and use data protection.
|
||||||
|
*/
|
||||||
|
public class PrivateNotificationService {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(PrivateNotificationService.class);
|
||||||
|
private final P2PService p2PService;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Constructor, Initialization
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public PrivateNotificationService(P2PService p2PService) {
|
||||||
|
this.p2PService = p2PService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDecryptedMailboxListener(DecryptedMailboxListener listener) {
|
||||||
|
p2PService.addDecryptedMailboxListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addDecryptedDirectMessageListener(DecryptedDirectMessageListener listener) {
|
||||||
|
p2PService.addDecryptedDirectMessageListener(listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void sendPrivateNotificationMessage(PrivateNotification privateNotification, Offer offer, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
|
||||||
|
p2PService.sendEncryptedMailboxMessage(offer.getOffererNodeAddress(),
|
||||||
|
offer.getPubKeyRing(),
|
||||||
|
new PrivateNotificationMessage(privateNotification, p2PService.getNetworkNode().getNodeAddress()),
|
||||||
|
new SendMailboxMessageListener() {
|
||||||
|
@Override
|
||||||
|
public void onArrived() {
|
||||||
|
log.trace("PrivateNotificationMessage arrived at peer. PrivateNotificationMessage = " + privateNotification);
|
||||||
|
if (resultHandler != null) resultHandler.handleResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStoredInMailbox() {
|
||||||
|
log.trace("PrivateNotificationMessage was stored in mailbox. PrivateNotificationMessage = " + privateNotification);
|
||||||
|
if (resultHandler != null) resultHandler.handleResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFault(String errorMessage) {
|
||||||
|
if (errorMessageHandler != null)
|
||||||
|
errorMessageHandler.handleErrorMessage("Add privateNotificationMessage failed");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePrivateNotificationMessage(PrivateNotification privateNotification, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,6 +1,8 @@
|
|||||||
package io.bitsquare.gui.components;
|
package io.bitsquare.gui.components;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.gui.main.overlays.editor.PeerInfoWithTagEditor;
|
import io.bitsquare.gui.main.overlays.editor.PeerInfoWithTagEditor;
|
||||||
|
import io.bitsquare.trade.offer.Offer;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Group;
|
import javafx.scene.Group;
|
||||||
@ -24,6 +26,8 @@ public class PeerInfoIcon extends Group {
|
|||||||
private final String hostName;
|
private final String hostName;
|
||||||
private final String tooltipText;
|
private final String tooltipText;
|
||||||
private final int numTrades;
|
private final int numTrades;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
|
private Offer offer;
|
||||||
private final Map<String, String> peerTagMap;
|
private final Map<String, String> peerTagMap;
|
||||||
private final Label numTradesLabel;
|
private final Label numTradesLabel;
|
||||||
private final double SIZE = 26;
|
private final double SIZE = 26;
|
||||||
@ -33,10 +37,12 @@ public class PeerInfoIcon extends Group {
|
|||||||
private final Pane tagPane;
|
private final Pane tagPane;
|
||||||
private final Pane numTradesPane;
|
private final Pane numTradesPane;
|
||||||
|
|
||||||
public PeerInfoIcon(String hostName, String tooltipText, int numTrades) {
|
public PeerInfoIcon(String hostName, String tooltipText, int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer) {
|
||||||
this.hostName = hostName;
|
this.hostName = hostName;
|
||||||
this.tooltipText = tooltipText;
|
this.tooltipText = tooltipText;
|
||||||
this.numTrades = numTrades;
|
this.numTrades = numTrades;
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
|
this.offer = offer;
|
||||||
|
|
||||||
peerTagMap = Preferences.INSTANCE.getPeerTagMap();
|
peerTagMap = Preferences.INSTANCE.getPeerTagMap();
|
||||||
|
|
||||||
@ -97,7 +103,7 @@ public class PeerInfoIcon extends Group {
|
|||||||
|
|
||||||
getChildren().addAll(background, avatarImageView, tagPane, numTradesPane);
|
getChildren().addAll(background, avatarImageView, tagPane, numTradesPane);
|
||||||
|
|
||||||
setOnMouseClicked(e -> new PeerInfoWithTagEditor()
|
setOnMouseClicked(e -> new PeerInfoWithTagEditor(privateNotificationManager, offer)
|
||||||
.hostName(hostName)
|
.hostName(hostName)
|
||||||
.numTrades(numTrades)
|
.numTrades(numTrades)
|
||||||
.position(localToScene(new Point2D(0, 0)))
|
.position(localToScene(new Point2D(0, 0)))
|
||||||
|
@ -20,6 +20,8 @@ package io.bitsquare.gui.main;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import io.bitsquare.alert.Alert;
|
import io.bitsquare.alert.Alert;
|
||||||
import io.bitsquare.alert.AlertManager;
|
import io.bitsquare.alert.AlertManager;
|
||||||
|
import io.bitsquare.alert.PrivateNotification;
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.app.BitsquareApp;
|
import io.bitsquare.app.BitsquareApp;
|
||||||
import io.bitsquare.app.DevFlags;
|
import io.bitsquare.app.DevFlags;
|
||||||
import io.bitsquare.app.Log;
|
import io.bitsquare.app.Log;
|
||||||
@ -101,6 +103,7 @@ public class MainViewModel implements ViewModel {
|
|||||||
private final DisputeManager disputeManager;
|
private final DisputeManager disputeManager;
|
||||||
final Preferences preferences;
|
final Preferences preferences;
|
||||||
private final AlertManager alertManager;
|
private final AlertManager alertManager;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
private final WalletPasswordWindow walletPasswordWindow;
|
private final WalletPasswordWindow walletPasswordWindow;
|
||||||
private final NotificationCenter notificationCenter;
|
private final NotificationCenter notificationCenter;
|
||||||
private final TacWindow tacWindow;
|
private final TacWindow tacWindow;
|
||||||
@ -171,7 +174,8 @@ public class MainViewModel implements ViewModel {
|
|||||||
PriceFeed priceFeed,
|
PriceFeed priceFeed,
|
||||||
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
|
ArbitratorManager arbitratorManager, P2PService p2PService, TradeManager tradeManager,
|
||||||
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
|
OpenOfferManager openOfferManager, DisputeManager disputeManager, Preferences preferences,
|
||||||
User user, AlertManager alertManager, WalletPasswordWindow walletPasswordWindow,
|
User user, AlertManager alertManager, PrivateNotificationManager privateNotificationManager,
|
||||||
|
WalletPasswordWindow walletPasswordWindow,
|
||||||
NotificationCenter notificationCenter, TacWindow tacWindow, Clock clock,
|
NotificationCenter notificationCenter, TacWindow tacWindow, Clock clock,
|
||||||
KeyRing keyRing, Navigation navigation, BSFormatter formatter) {
|
KeyRing keyRing, Navigation navigation, BSFormatter formatter) {
|
||||||
this.priceFeed = priceFeed;
|
this.priceFeed = priceFeed;
|
||||||
@ -185,6 +189,7 @@ public class MainViewModel implements ViewModel {
|
|||||||
this.disputeManager = disputeManager;
|
this.disputeManager = disputeManager;
|
||||||
this.preferences = preferences;
|
this.preferences = preferences;
|
||||||
this.alertManager = alertManager;
|
this.alertManager = alertManager;
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
this.walletPasswordWindow = walletPasswordWindow;
|
this.walletPasswordWindow = walletPasswordWindow;
|
||||||
this.notificationCenter = notificationCenter;
|
this.notificationCenter = notificationCenter;
|
||||||
this.tacWindow = tacWindow;
|
this.tacWindow = tacWindow;
|
||||||
@ -517,6 +522,7 @@ public class MainViewModel implements ViewModel {
|
|||||||
openOfferManager.onAllServicesInitialized();
|
openOfferManager.onAllServicesInitialized();
|
||||||
arbitratorManager.onAllServicesInitialized();
|
arbitratorManager.onAllServicesInitialized();
|
||||||
alertManager.alertMessageProperty().addListener((observable, oldValue, newValue) -> displayAlertIfPresent(newValue));
|
alertManager.alertMessageProperty().addListener((observable, oldValue, newValue) -> displayAlertIfPresent(newValue));
|
||||||
|
privateNotificationManager.privateNotificationProperty().addListener((observable, oldValue, newValue) -> displayPrivateNotification(newValue));
|
||||||
displayAlertIfPresent(alertManager.alertMessageProperty().get());
|
displayAlertIfPresent(alertManager.alertMessageProperty().get());
|
||||||
|
|
||||||
setupBtcNumPeersWatcher();
|
setupBtcNumPeersWatcher();
|
||||||
@ -865,6 +871,12 @@ public class MainViewModel implements ViewModel {
|
|||||||
new DisplayAlertMessageWindow().alertMessage(alert).show();
|
new DisplayAlertMessageWindow().alertMessage(alert).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void displayPrivateNotification(PrivateNotification privateNotification) {
|
||||||
|
new Popup<>().headLine("Important notification from Bitsquare developers!")
|
||||||
|
.information(privateNotification.message)
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
private void swapPendingOfferFundingEntries() {
|
private void swapPendingOfferFundingEntries() {
|
||||||
tradeManager.getAddressEntriesForAvailableBalanceStream()
|
tradeManager.getAddressEntriesForAvailableBalanceStream()
|
||||||
.filter(addressEntry -> addressEntry.getOfferId() != null)
|
.filter(addressEntry -> addressEntry.getOfferId() != null)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.gui.main.offer.offerbook;
|
package io.bitsquare.gui.main.offer.offerbook;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.gui.Navigation;
|
import io.bitsquare.gui.Navigation;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
@ -68,6 +69,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||||||
private final Navigation navigation;
|
private final Navigation navigation;
|
||||||
private final OfferDetailsWindow offerDetailsWindow;
|
private final OfferDetailsWindow offerDetailsWindow;
|
||||||
private BSFormatter formatter;
|
private BSFormatter formatter;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
|
|
||||||
private ComboBox<TradeCurrency> currencyComboBox;
|
private ComboBox<TradeCurrency> currencyComboBox;
|
||||||
private ComboBox<PaymentMethod> paymentMethodComboBox;
|
private ComboBox<PaymentMethod> paymentMethodComboBox;
|
||||||
@ -87,12 +89,13 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
OfferBookView(OfferBookViewModel model, Navigation navigation, OfferDetailsWindow offerDetailsWindow, BSFormatter formatter) {
|
OfferBookView(OfferBookViewModel model, Navigation navigation, OfferDetailsWindow offerDetailsWindow, BSFormatter formatter, PrivateNotificationManager privateNotificationManager) {
|
||||||
super(model);
|
super(model);
|
||||||
|
|
||||||
this.navigation = navigation;
|
this.navigation = navigation;
|
||||||
this.offerDetailsWindow = offerDetailsWindow;
|
this.offerDetailsWindow = offerDetailsWindow;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -706,7 +709,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||||||
boolean hasTraded = numPastTrades > 0;
|
boolean hasTraded = numPastTrades > 0;
|
||||||
String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" +
|
String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" +
|
||||||
"You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName;
|
"You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName;
|
||||||
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades);
|
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades, privateNotificationManager, newItem.getOffer());
|
||||||
setPadding(new Insets(-2, 0, -2, 0));
|
setPadding(new Insets(-2, 0, -2, 0));
|
||||||
if (identIcon != null)
|
if (identIcon != null)
|
||||||
setGraphic(identIcon);
|
setGraphic(identIcon);
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
package io.bitsquare.gui.main.overlays.editor;
|
package io.bitsquare.gui.main.overlays.editor;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.gui.components.InputTextField;
|
import io.bitsquare.gui.components.InputTextField;
|
||||||
import io.bitsquare.gui.main.overlays.Overlay;
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
|
import io.bitsquare.gui.main.overlays.windows.SendPrivateNotificationWindow;
|
||||||
import io.bitsquare.gui.util.FormBuilder;
|
import io.bitsquare.gui.util.FormBuilder;
|
||||||
|
import io.bitsquare.trade.offer.Offer;
|
||||||
import io.bitsquare.user.Preferences;
|
import io.bitsquare.user.Preferences;
|
||||||
import javafx.animation.Interpolator;
|
import javafx.animation.Interpolator;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
@ -16,6 +19,7 @@ import javafx.geometry.Point2D;
|
|||||||
import javafx.scene.Camera;
|
import javafx.scene.Camera;
|
||||||
import javafx.scene.PerspectiveCamera;
|
import javafx.scene.PerspectiveCamera;
|
||||||
import javafx.scene.Scene;
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
import javafx.scene.input.KeyCode;
|
import javafx.scene.input.KeyCode;
|
||||||
import javafx.scene.layout.GridPane;
|
import javafx.scene.layout.GridPane;
|
||||||
import javafx.scene.transform.Rotate;
|
import javafx.scene.transform.Rotate;
|
||||||
@ -38,9 +42,13 @@ public class PeerInfoWithTagEditor extends Overlay<PeerInfoWithTagEditor> {
|
|||||||
private String hostName;
|
private String hostName;
|
||||||
private int numTrades;
|
private int numTrades;
|
||||||
private ChangeListener<Boolean> focusListener;
|
private ChangeListener<Boolean> focusListener;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
|
private Offer offer;
|
||||||
|
|
||||||
|
|
||||||
public PeerInfoWithTagEditor() {
|
public PeerInfoWithTagEditor(PrivateNotificationManager privateNotificationManager, Offer offer) {
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
|
this.offer = offer;
|
||||||
width = 400;
|
width = 400;
|
||||||
type = Type.Undefined;
|
type = Type.Undefined;
|
||||||
if (INSTANCE != null)
|
if (INSTANCE != null)
|
||||||
@ -123,6 +131,14 @@ public class PeerInfoWithTagEditor extends Overlay<PeerInfoWithTagEditor> {
|
|||||||
Map<String, String> peerTagMap = Preferences.INSTANCE.getPeerTagMap();
|
Map<String, String> peerTagMap = Preferences.INSTANCE.getPeerTagMap();
|
||||||
String tag = peerTagMap.containsKey(hostName) ? peerTagMap.get(hostName) : "";
|
String tag = peerTagMap.containsKey(hostName) ? peerTagMap.get(hostName) : "";
|
||||||
inputTextField.setText(tag);
|
inputTextField.setText(tag);
|
||||||
|
|
||||||
|
Button button = FormBuilder.addButton(gridPane, ++rowIndex, "Send private message");
|
||||||
|
button.setOnAction(e -> {
|
||||||
|
new SendPrivateNotificationWindow(offer)
|
||||||
|
.onAddAlertMessage(privateNotificationManager::sendPrivateNotificationMessageIfKeyIsValid)
|
||||||
|
.onRemoveAlertMessage(privateNotificationManager::removePrivateNotificationMessageIfKeyIsValid)
|
||||||
|
.show();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Bitsquare.
|
||||||
|
*
|
||||||
|
* Bitsquare 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.
|
||||||
|
*
|
||||||
|
* Bitsquare 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 Bitsquare. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.bitsquare.gui.main.overlays.windows;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotification;
|
||||||
|
import io.bitsquare.common.util.Tuple2;
|
||||||
|
import io.bitsquare.gui.components.InputTextField;
|
||||||
|
import io.bitsquare.gui.main.overlays.Overlay;
|
||||||
|
import io.bitsquare.gui.main.overlays.popups.Popup;
|
||||||
|
import io.bitsquare.trade.offer.Offer;
|
||||||
|
import javafx.geometry.Insets;
|
||||||
|
import javafx.scene.Scene;
|
||||||
|
import javafx.scene.control.Button;
|
||||||
|
import javafx.scene.control.Label;
|
||||||
|
import javafx.scene.control.TextArea;
|
||||||
|
import javafx.scene.input.KeyCode;
|
||||||
|
import javafx.scene.layout.GridPane;
|
||||||
|
import javafx.scene.layout.HBox;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.addLabelInputTextField;
|
||||||
|
import static io.bitsquare.gui.util.FormBuilder.addLabelTextArea;
|
||||||
|
|
||||||
|
public class SendPrivateNotificationWindow extends Overlay<SendPrivateNotificationWindow> {
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(SendPrivateNotificationWindow.class);
|
||||||
|
private Button sendButton;
|
||||||
|
private SendPrivateNotificationHandler sendPrivateNotificationHandler;
|
||||||
|
private RemoveAlertMessageHandler removeAlertMessageHandler;
|
||||||
|
private Offer offer;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Interface
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
public interface SendPrivateNotificationHandler {
|
||||||
|
boolean handle(PrivateNotification privateNotification, Offer offer, String privKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface RemoveAlertMessageHandler {
|
||||||
|
boolean handle(String privKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Public API
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
public SendPrivateNotificationWindow(Offer offer) {
|
||||||
|
this.offer = offer;
|
||||||
|
type = Type.Attention;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
if (headLine == null)
|
||||||
|
headLine = "Edit ban list";
|
||||||
|
|
||||||
|
width = 600;
|
||||||
|
createGridPane();
|
||||||
|
addHeadLine();
|
||||||
|
addSeparator();
|
||||||
|
addContent();
|
||||||
|
applyStyles();
|
||||||
|
display();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SendPrivateNotificationWindow onAddAlertMessage(SendPrivateNotificationHandler sendPrivateNotificationHandler) {
|
||||||
|
this.sendPrivateNotificationHandler = sendPrivateNotificationHandler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SendPrivateNotificationWindow onRemoveAlertMessage(RemoveAlertMessageHandler removeAlertMessageHandler) {
|
||||||
|
this.removeAlertMessageHandler = removeAlertMessageHandler;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Protected
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void setupKeyHandler(Scene scene) {
|
||||||
|
if (!hideCloseButton) {
|
||||||
|
scene.setOnKeyPressed(e -> {
|
||||||
|
if (e.getCode() == KeyCode.ESCAPE) {
|
||||||
|
e.consume();
|
||||||
|
doClose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addContent() {
|
||||||
|
InputTextField keyInputTextField = addLabelInputTextField(gridPane, ++rowIndex, "Ban list private key:", 10).second;
|
||||||
|
Tuple2<Label, TextArea> labelTextAreaTuple2 = addLabelTextArea(gridPane, ++rowIndex, "Private alert message:", "Enter message");
|
||||||
|
TextArea alertMessageTextArea = labelTextAreaTuple2.second;
|
||||||
|
Label first = labelTextAreaTuple2.first;
|
||||||
|
first.setMinWidth(150);
|
||||||
|
|
||||||
|
sendButton = new Button("Send private alert message");
|
||||||
|
sendButton.setOnAction(e -> {
|
||||||
|
if (alertMessageTextArea.getText().length() > 0 && keyInputTextField.getText().length() > 0) {
|
||||||
|
if (sendPrivateNotificationHandler.handle(
|
||||||
|
new PrivateNotification(alertMessageTextArea.getText()),
|
||||||
|
offer,
|
||||||
|
keyInputTextField.getText()))
|
||||||
|
hide();
|
||||||
|
else
|
||||||
|
new Popup().warning("The key you entered was not correct.").width(300).onClose(() -> blurAgain()).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Button removeAlertMessageButton = new Button("Remove notification");
|
||||||
|
removeAlertMessageButton.setOnAction(e -> {
|
||||||
|
if (keyInputTextField.getText().length() > 0) {
|
||||||
|
if (removeAlertMessageHandler.handle(keyInputTextField.getText()))
|
||||||
|
hide();
|
||||||
|
else
|
||||||
|
new Popup().warning("The key you entered was not correct.").width(300).onClose(() -> blurAgain()).show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
closeButton = new Button("Close");
|
||||||
|
closeButton.setOnAction(e -> {
|
||||||
|
hide();
|
||||||
|
closeHandlerOptional.ifPresent(closeHandler -> closeHandler.run());
|
||||||
|
});
|
||||||
|
|
||||||
|
HBox hBox = new HBox();
|
||||||
|
hBox.setSpacing(10);
|
||||||
|
GridPane.setRowIndex(hBox, ++rowIndex);
|
||||||
|
GridPane.setColumnIndex(hBox, 1);
|
||||||
|
hBox.getChildren().addAll(sendButton, removeAlertMessageButton, closeButton);
|
||||||
|
gridPane.getChildren().add(hBox);
|
||||||
|
GridPane.setMargin(hBox, new Insets(10, 0, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.closedtrades;
|
package io.bitsquare.gui.main.portfolio.closedtrades;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
import io.bitsquare.gui.components.HyperlinkWithIcon;
|
||||||
@ -52,14 +53,16 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
|||||||
private final BSFormatter formatter;
|
private final BSFormatter formatter;
|
||||||
private final OfferDetailsWindow offerDetailsWindow;
|
private final OfferDetailsWindow offerDetailsWindow;
|
||||||
private final TradeDetailsWindow tradeDetailsWindow;
|
private final TradeDetailsWindow tradeDetailsWindow;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
private SortedList<ClosedTradableListItem> sortedList;
|
private SortedList<ClosedTradableListItem> sortedList;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ClosedTradesView(ClosedTradesViewModel model, BSFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow) {
|
public ClosedTradesView(ClosedTradesViewModel model, BSFormatter formatter, OfferDetailsWindow offerDetailsWindow, TradeDetailsWindow tradeDetailsWindow, PrivateNotificationManager privateNotificationManager) {
|
||||||
super(model);
|
super(model);
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
this.offerDetailsWindow = offerDetailsWindow;
|
this.offerDetailsWindow = offerDetailsWindow;
|
||||||
this.tradeDetailsWindow = tradeDetailsWindow;
|
this.tradeDetailsWindow = tradeDetailsWindow;
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -235,7 +238,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
|||||||
|
|
||||||
int numPastTrades = model.getNumPastTrades(newItem.getTradable());
|
int numPastTrades = model.getNumPastTrades(newItem.getTradable());
|
||||||
String hostName = ((Trade) newItem.getTradable()).getTradingPeerNodeAddress().hostName;
|
String hostName = ((Trade) newItem.getTradable()).getTradingPeerNodeAddress().hostName;
|
||||||
Node identIcon = new PeerInfoIcon(hostName, "Trading peers onion address: " + hostName, numPastTrades);
|
Node identIcon = new PeerInfoIcon(hostName, "Trading peers onion address: " + hostName, numPastTrades, privateNotificationManager, newItem.getTradable().getOffer());
|
||||||
setPadding(new Insets(-2, 0, -2, 0));
|
setPadding(new Insets(-2, 0, -2, 0));
|
||||||
if (identIcon != null)
|
if (identIcon != null)
|
||||||
setGraphic(identIcon);
|
setGraphic(identIcon);
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
package io.bitsquare.gui.main.portfolio.pendingtrades;
|
||||||
|
|
||||||
|
import io.bitsquare.alert.PrivateNotificationManager;
|
||||||
import io.bitsquare.common.UserThread;
|
import io.bitsquare.common.UserThread;
|
||||||
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
import io.bitsquare.gui.common.view.ActivatableViewAndModel;
|
||||||
import io.bitsquare.gui.common.view.FxmlView;
|
import io.bitsquare.gui.common.view.FxmlView;
|
||||||
@ -50,6 +51,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||||||
|
|
||||||
private final TradeDetailsWindow tradeDetailsWindow;
|
private final TradeDetailsWindow tradeDetailsWindow;
|
||||||
private final BSFormatter formatter;
|
private final BSFormatter formatter;
|
||||||
|
private PrivateNotificationManager privateNotificationManager;
|
||||||
@FXML
|
@FXML
|
||||||
TableView<PendingTradesListItem> tableView;
|
TableView<PendingTradesListItem> tableView;
|
||||||
@FXML
|
@FXML
|
||||||
@ -70,10 +72,11 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public PendingTradesView(PendingTradesViewModel model, TradeDetailsWindow tradeDetailsWindow, BSFormatter formatter) {
|
public PendingTradesView(PendingTradesViewModel model, TradeDetailsWindow tradeDetailsWindow, BSFormatter formatter, PrivateNotificationManager privateNotificationManager) {
|
||||||
super(model);
|
super(model);
|
||||||
this.tradeDetailsWindow = tradeDetailsWindow;
|
this.tradeDetailsWindow = tradeDetailsWindow;
|
||||||
this.formatter = formatter;
|
this.formatter = formatter;
|
||||||
|
this.privateNotificationManager = privateNotificationManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -454,7 +457,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||||||
boolean hasTraded = numPastTrades > 0;
|
boolean hasTraded = numPastTrades > 0;
|
||||||
String tooltipText = hasTraded ? "Trading peers onion address: " + hostName + "\n" +
|
String tooltipText = hasTraded ? "Trading peers onion address: " + hostName + "\n" +
|
||||||
"You have already traded " + numPastTrades + " times with that peer." : "Trading peers onion address: " + hostName;
|
"You have already traded " + numPastTrades + " times with that peer." : "Trading peers onion address: " + hostName;
|
||||||
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades);
|
Node identIcon = new PeerInfoIcon(hostName, tooltipText, numPastTrades, privateNotificationManager, newItem.getTrade().getOffer());
|
||||||
setPadding(new Insets(-2, 0, -2, 0));
|
setPadding(new Insets(-2, 0, -2, 0));
|
||||||
if (identIcon != null)
|
if (identIcon != null)
|
||||||
setGraphic(identIcon);
|
setGraphic(identIcon);
|
||||||
|
Loading…
Reference in New Issue
Block a user