mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-23 23:06:39 +01:00
Merge pull request #5559 from jmacxx/dispute_tag_avatar
Feature to enable disputes user avatars and tag editing
This commit is contained in:
commit
ddd2ab490b
11 changed files with 345 additions and 182 deletions
|
@ -3071,6 +3071,7 @@ peerInfoIcon.tooltip.trade.traded={0} onion address: {1}\nYou have already trade
|
|||
peerInfoIcon.tooltip.trade.notTraded={0} onion address: {1}\nYou have not traded with that peer so far.\n{2}
|
||||
peerInfoIcon.tooltip.age=Payment account created {0} ago.
|
||||
peerInfoIcon.tooltip.unknownAge=Payment account age not known.
|
||||
peerInfoIcon.tooltip.dispute={0}\nNumber of disputes: {1}.\n{2}
|
||||
|
||||
tooltip.openPopupForDetails=Open popup for details
|
||||
tooltip.invalidTradeState.warning=This trade is in an invalid state. Open the details window for more information
|
||||
|
|
|
@ -20,23 +20,16 @@ package bisq.desktop.components;
|
|||
import bisq.desktop.main.overlays.editor.PeerInfoWithTagEditor;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
import bisq.core.alert.PrivateNotificationManager;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
import bisq.core.trade.Trade;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.util.Tuple5;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javafx.scene.Group;
|
||||
import javafx.scene.canvas.Canvas;
|
||||
import javafx.scene.canvas.GraphicsContext;
|
||||
|
@ -51,132 +44,37 @@ import javafx.geometry.Point2D;
|
|||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class PeerInfoIcon extends Group {
|
||||
private final String tooltipText;
|
||||
private final int numTrades;
|
||||
private final AccountAgeWitnessService accountAgeWitnessService;
|
||||
private final Map<String, String> peerTagMap;
|
||||
private final Label numTradesLabel;
|
||||
private final Label tagLabel;
|
||||
final Pane tagPane;
|
||||
final Pane numTradesPane;
|
||||
private final String fullAddress;
|
||||
|
||||
public PeerInfoIcon(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
Offer offer,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
this(nodeAddress,
|
||||
role,
|
||||
numTrades,
|
||||
privateNotificationManager,
|
||||
offer,
|
||||
null,
|
||||
preferences,
|
||||
accountAgeWitnessService,
|
||||
useDevPrivilegeKeys);
|
||||
|
||||
public interface notify {
|
||||
void avatarTagUpdated();
|
||||
}
|
||||
|
||||
public PeerInfoIcon(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
Trade trade,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
this(nodeAddress,
|
||||
role,
|
||||
numTrades,
|
||||
privateNotificationManager,
|
||||
trade.getOffer(),
|
||||
trade,
|
||||
preferences,
|
||||
accountAgeWitnessService,
|
||||
useDevPrivilegeKeys);
|
||||
@Setter
|
||||
private notify callback;
|
||||
protected Preferences preferences;
|
||||
protected final String fullAddress;
|
||||
protected String tooltipText;
|
||||
protected Label tagLabel;
|
||||
private Label numTradesLabel;
|
||||
protected Pane tagPane;
|
||||
protected Pane numTradesPane;
|
||||
protected int numTrades = 0;
|
||||
|
||||
public PeerInfoIcon(NodeAddress nodeAddress, Preferences preferences) {
|
||||
this.preferences = preferences;
|
||||
this.fullAddress = nodeAddress != null ? nodeAddress.getFullAddress() : "";
|
||||
}
|
||||
|
||||
private PeerInfoIcon(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
@Nullable Offer offer,
|
||||
@Nullable Trade trade,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
this.numTrades = numTrades;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
|
||||
protected void createAvatar(Color ringColor) {
|
||||
double scaleFactor = getScaleFactor();
|
||||
fullAddress = nodeAddress != null ? nodeAddress.getFullAddress() : "";
|
||||
|
||||
peerTagMap = preferences.getPeerTagMap();
|
||||
|
||||
boolean hasTraded = numTrades > 0;
|
||||
Tuple5<Long, Long, String, String, String> peersAccount = getPeersAccountAge(trade, offer);
|
||||
|
||||
Long accountAge = peersAccount.first;
|
||||
Long signAge = peersAccount.second;
|
||||
|
||||
if (offer == null) {
|
||||
checkNotNull(trade, "Trade must not be null if offer is null.");
|
||||
offer = trade.getOffer();
|
||||
}
|
||||
|
||||
checkNotNull(offer, "Offer must not be null");
|
||||
|
||||
boolean isFiatCurrency = CurrencyUtil.isFiatCurrency(offer.getCurrencyCode());
|
||||
|
||||
String accountAgeTooltip = isFiatCurrency ?
|
||||
accountAge > -1 ? Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(accountAge)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge") :
|
||||
"";
|
||||
tooltipText = hasTraded ?
|
||||
Res.get("peerInfoIcon.tooltip.trade.traded", role, fullAddress, numTrades, accountAgeTooltip) :
|
||||
Res.get("peerInfoIcon.tooltip.trade.notTraded", role, fullAddress, accountAgeTooltip);
|
||||
|
||||
// outer circle
|
||||
Color ringColor;
|
||||
if (isFiatCurrency) {
|
||||
|
||||
switch (accountAgeWitnessService.getPeersAccountAgeCategory(hasChargebackRisk(trade, offer) ? signAge : accountAge)) {
|
||||
case TWO_MONTHS_OR_MORE:
|
||||
ringColor = Color.rgb(0, 225, 0); // > 2 months green
|
||||
break;
|
||||
case ONE_TO_TWO_MONTHS:
|
||||
ringColor = Color.rgb(0, 139, 205); // 1-2 months blue
|
||||
break;
|
||||
case LESS_ONE_MONTH:
|
||||
ringColor = Color.rgb(255, 140, 0); //< 1 month orange
|
||||
break;
|
||||
case UNVERIFIED:
|
||||
default:
|
||||
ringColor = Color.rgb(255, 0, 0); // not signed, red
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// for altcoins we always display green
|
||||
ringColor = Color.rgb(0, 225, 0);
|
||||
}
|
||||
|
||||
double outerSize = 26 * scaleFactor;
|
||||
Canvas outerBackground = new Canvas(outerSize, outerSize);
|
||||
GraphicsContext outerBackgroundGc = outerBackground.getGraphicsContext2D();
|
||||
|
@ -245,54 +143,6 @@ public class PeerInfoIcon extends Group {
|
|||
updatePeerInfoIcon();
|
||||
|
||||
getChildren().addAll(outerBackground, innerBackground, avatarImageView, tagPane, numTradesPane);
|
||||
|
||||
addMouseListener(numTrades, privateNotificationManager, trade, offer, preferences, useDevPrivilegeKeys,
|
||||
isFiatCurrency, accountAge, signAge, peersAccount.third, peersAccount.fourth, peersAccount.fifth);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trade Open trade for trading peer info to be shown
|
||||
* @param offer Open offer for trading peer info to be shown
|
||||
* @return account age, sign age, account info, sign info, sign state
|
||||
*/
|
||||
private Tuple5<Long, Long, String, String, String> getPeersAccountAge(@Nullable Trade trade,
|
||||
@Nullable Offer offer) {
|
||||
AccountAgeWitnessService.SignState signState;
|
||||
long signAge = -1L;
|
||||
long accountAge = -1L;
|
||||
|
||||
if (trade != null) {
|
||||
offer = trade.getOffer();
|
||||
if (offer == null) {
|
||||
// unexpected
|
||||
return new Tuple5<>(signAge, accountAge, Res.get("peerInfo.age.noRisk"), null, null);
|
||||
}
|
||||
signState = accountAgeWitnessService.getSignState(trade);
|
||||
signAge = accountAgeWitnessService.getWitnessSignAge(trade, new Date());
|
||||
accountAge = accountAgeWitnessService.getAccountAge(trade);
|
||||
} else {
|
||||
checkNotNull(offer, "Offer must not be null if trade is null.");
|
||||
signState = accountAgeWitnessService.getSignState(offer);
|
||||
signAge = accountAgeWitnessService.getWitnessSignAge(offer, new Date());
|
||||
accountAge = accountAgeWitnessService.getAccountAge(offer);
|
||||
}
|
||||
|
||||
if (hasChargebackRisk(trade, offer)) {
|
||||
String signAgeInfo = Res.get("peerInfo.age.chargeBackRisk");
|
||||
String accountSigningState = StringUtils.capitalize(signState.getDisplayString());
|
||||
if (signState.equals(AccountAgeWitnessService.SignState.UNSIGNED))
|
||||
signAgeInfo = null;
|
||||
|
||||
return new Tuple5<>(accountAge, signAge, Res.get("peerInfo.age.noRisk"), signAgeInfo, accountSigningState);
|
||||
}
|
||||
return new Tuple5<>(accountAge, signAge, Res.get("peerInfo.age.noRisk"), null, null);
|
||||
}
|
||||
|
||||
private boolean hasChargebackRisk(@Nullable Trade trade, @Nullable Offer offer) {
|
||||
Offer offerToCheck = trade != null ? trade.getOffer() : offer;
|
||||
|
||||
return offerToCheck != null &&
|
||||
PaymentMethod.hasChargebackRisk(offerToCheck.getPaymentMethod(), offerToCheck.getCurrencyCode());
|
||||
}
|
||||
|
||||
protected void addMouseListener(int numTrades,
|
||||
|
@ -332,6 +182,9 @@ public class PeerInfoIcon extends Group {
|
|||
.onSave(newTag -> {
|
||||
preferences.setTagForPeer(fullAddress, newTag);
|
||||
updatePeerInfoIcon();
|
||||
if (callback != null) {
|
||||
callback.avatarTagUpdated();
|
||||
}
|
||||
})
|
||||
.show());
|
||||
}
|
||||
|
@ -340,8 +193,15 @@ public class PeerInfoIcon extends Group {
|
|||
return 1;
|
||||
}
|
||||
|
||||
protected String getAccountAgeTooltip(Long accountAge) {
|
||||
return accountAge > -1 ?
|
||||
Res.get("peerInfoIcon.tooltip.age", DisplayUtils.formatAccountAge(accountAge)) :
|
||||
Res.get("peerInfoIcon.tooltip.unknownAge");
|
||||
}
|
||||
|
||||
protected void updatePeerInfoIcon() {
|
||||
String tag;
|
||||
Map<String, String> peerTagMap = preferences.getPeerTagMap();
|
||||
if (peerTagMap.containsKey(fullAddress)) {
|
||||
tag = peerTagMap.get(fullAddress);
|
||||
final String text = !tag.isEmpty() ? Res.get("peerInfoIcon.tooltip", tooltipText, tag) : tooltipText;
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.components;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import static bisq.desktop.util.Colors.AVATAR_GREY;
|
||||
|
||||
@Slf4j
|
||||
public class PeerInfoIconDispute extends PeerInfoIcon {
|
||||
|
||||
public PeerInfoIconDispute(NodeAddress nodeAddress,
|
||||
String nrOfDisputes,
|
||||
long accountAge,
|
||||
Preferences preferences) {
|
||||
super(nodeAddress, preferences);
|
||||
|
||||
tooltipText = Res.get("peerInfoIcon.tooltip.dispute", fullAddress, nrOfDisputes, getAccountAgeTooltip(accountAge));
|
||||
|
||||
// outer circle always display gray
|
||||
createAvatar(AVATAR_GREY);
|
||||
addMouseListener(numTrades, null, null, null, preferences, false,
|
||||
false, accountAge, 0L, null, null, null);
|
||||
}
|
||||
|
||||
public void refreshTag() {
|
||||
updatePeerInfoIcon();
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@ import bisq.network.p2p.NodeAddress;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class PeerInfoIconSmall extends PeerInfoIcon {
|
||||
public class PeerInfoIconSmall extends PeerInfoIconTrading {
|
||||
public PeerInfoIconSmall(NodeAddress nodeAddress,
|
||||
String role,
|
||||
Offer offer,
|
||||
|
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* 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.components;
|
||||
|
||||
import bisq.core.account.witness.AccountAgeWitnessService;
|
||||
import bisq.core.alert.PrivateNotificationManager;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.payment.payload.PaymentMethod;
|
||||
import bisq.core.trade.Trade;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.util.Tuple5;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javafx.scene.paint.Color;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static bisq.desktop.util.Colors.*;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@Slf4j
|
||||
public class PeerInfoIconTrading extends PeerInfoIcon {
|
||||
private final AccountAgeWitnessService accountAgeWitnessService;
|
||||
private boolean isFiatCurrency;
|
||||
|
||||
public PeerInfoIconTrading(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
Offer offer,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
this(nodeAddress,
|
||||
role,
|
||||
numTrades,
|
||||
privateNotificationManager,
|
||||
offer,
|
||||
null,
|
||||
preferences,
|
||||
accountAgeWitnessService,
|
||||
useDevPrivilegeKeys);
|
||||
}
|
||||
|
||||
public PeerInfoIconTrading(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
Trade trade,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
this(nodeAddress,
|
||||
role,
|
||||
numTrades,
|
||||
privateNotificationManager,
|
||||
trade.getOffer(),
|
||||
trade,
|
||||
preferences,
|
||||
accountAgeWitnessService,
|
||||
useDevPrivilegeKeys);
|
||||
}
|
||||
|
||||
private PeerInfoIconTrading(NodeAddress nodeAddress,
|
||||
String role,
|
||||
int numTrades,
|
||||
PrivateNotificationManager privateNotificationManager,
|
||||
@Nullable Offer offer,
|
||||
@Nullable Trade trade,
|
||||
Preferences preferences,
|
||||
AccountAgeWitnessService accountAgeWitnessService,
|
||||
boolean useDevPrivilegeKeys) {
|
||||
super(nodeAddress, preferences);
|
||||
this.numTrades = numTrades;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
if (offer == null) {
|
||||
checkNotNull(trade, "Trade must not be null if offer is null.");
|
||||
offer = trade.getOffer();
|
||||
}
|
||||
checkNotNull(offer, "Offer must not be null");
|
||||
isFiatCurrency = offer != null && CurrencyUtil.isFiatCurrency(offer.getCurrencyCode());
|
||||
initialize(role, offer, trade, privateNotificationManager, useDevPrivilegeKeys);
|
||||
}
|
||||
|
||||
protected void initialize(String role, Offer offer, Trade trade, PrivateNotificationManager privateNotificationManager, boolean useDevPrivilegeKeys) {
|
||||
boolean hasTraded = numTrades > 0;
|
||||
Tuple5<Long, Long, String, String, String> peersAccount = getPeersAccountAge(trade, offer);
|
||||
|
||||
Long accountAge = peersAccount.first;
|
||||
Long signAge = peersAccount.second;
|
||||
|
||||
tooltipText = hasTraded ?
|
||||
Res.get("peerInfoIcon.tooltip.trade.traded", role, fullAddress, numTrades, getAccountAgeTooltip(accountAge)) :
|
||||
Res.get("peerInfoIcon.tooltip.trade.notTraded", role, fullAddress, getAccountAgeTooltip(accountAge));
|
||||
|
||||
createAvatar(getRingColor(offer, trade, accountAge, signAge));
|
||||
addMouseListener(numTrades, privateNotificationManager, trade, offer, preferences, useDevPrivilegeKeys,
|
||||
isFiatCurrency, accountAge, signAge, peersAccount.third, peersAccount.fourth, peersAccount.fifth);
|
||||
}
|
||||
|
||||
protected String getAccountAgeTooltip(Long accountAge) {
|
||||
return isFiatCurrency ? super.getAccountAgeTooltip(accountAge) : "";
|
||||
}
|
||||
|
||||
protected Color getRingColor(Offer offer, Trade trade, Long accountAge, Long signAge) {
|
||||
// outer circle
|
||||
// for altcoins we always display green
|
||||
Color ringColor = AVATAR_GREEN;
|
||||
if (isFiatCurrency) {
|
||||
switch (accountAgeWitnessService.getPeersAccountAgeCategory(hasChargebackRisk(trade, offer) ? signAge : accountAge)) {
|
||||
case TWO_MONTHS_OR_MORE:
|
||||
ringColor = AVATAR_GREEN;
|
||||
break;
|
||||
case ONE_TO_TWO_MONTHS:
|
||||
ringColor = AVATAR_BLUE;
|
||||
break;
|
||||
case LESS_ONE_MONTH:
|
||||
ringColor = AVATAR_ORANGE;
|
||||
break;
|
||||
case UNVERIFIED:
|
||||
default:
|
||||
ringColor = AVATAR_RED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ringColor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param trade Open trade for trading peer info to be shown
|
||||
* @param offer Open offer for trading peer info to be shown
|
||||
* @return account age, sign age, account info, sign info, sign state
|
||||
*/
|
||||
private Tuple5<Long, Long, String, String, String> getPeersAccountAge(@Nullable Trade trade,
|
||||
@Nullable Offer offer) {
|
||||
AccountAgeWitnessService.SignState signState;
|
||||
long signAge = -1L;
|
||||
long accountAge = -1L;
|
||||
|
||||
if (trade != null) {
|
||||
offer = trade.getOffer();
|
||||
if (offer == null) {
|
||||
// unexpected
|
||||
return new Tuple5<>(signAge, accountAge, Res.get("peerInfo.age.noRisk"), null, null);
|
||||
}
|
||||
signState = accountAgeWitnessService.getSignState(trade);
|
||||
signAge = accountAgeWitnessService.getWitnessSignAge(trade, new Date());
|
||||
accountAge = accountAgeWitnessService.getAccountAge(trade);
|
||||
} else {
|
||||
checkNotNull(offer, "Offer must not be null if trade is null.");
|
||||
signState = accountAgeWitnessService.getSignState(offer);
|
||||
signAge = accountAgeWitnessService.getWitnessSignAge(offer, new Date());
|
||||
accountAge = accountAgeWitnessService.getAccountAge(offer);
|
||||
}
|
||||
|
||||
if (hasChargebackRisk(trade, offer)) {
|
||||
String signAgeInfo = Res.get("peerInfo.age.chargeBackRisk");
|
||||
String accountSigningState = StringUtils.capitalize(signState.getDisplayString());
|
||||
if (signState.equals(AccountAgeWitnessService.SignState.UNSIGNED))
|
||||
signAgeInfo = null;
|
||||
|
||||
return new Tuple5<>(accountAge, signAge, Res.get("peerInfo.age.noRisk"), signAgeInfo, accountSigningState);
|
||||
}
|
||||
return new Tuple5<>(accountAge, signAge, Res.get("peerInfo.age.noRisk"), null, null);
|
||||
}
|
||||
|
||||
private static boolean hasChargebackRisk(@Nullable Trade trade, @Nullable Offer offer) {
|
||||
Offer offerToCheck = trade != null ? trade.getOffer() : offer;
|
||||
|
||||
return offerToCheck != null &&
|
||||
PaymentMethod.hasChargebackRisk(offerToCheck.getPaymentMethod(), offerToCheck.getCurrencyCode());
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import bisq.desktop.components.AutocompleteComboBox;
|
|||
import bisq.desktop.components.ColoredDecimalPlacesWithZerosText;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.InfoAutoTooltipLabel;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.components.PeerInfoIconTrading;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.account.AccountView;
|
||||
|
@ -1175,7 +1175,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
|
|||
final NodeAddress makersNodeAddress = offer.getOwnerNodeAddress();
|
||||
String role = Res.get("peerInfoIcon.tooltip.maker");
|
||||
int numTrades = model.getNumTrades(offer);
|
||||
PeerInfoIcon peerInfoIcon = new PeerInfoIcon(makersNodeAddress,
|
||||
PeerInfoIconTrading peerInfoIcon = new PeerInfoIconTrading(makersNodeAddress,
|
||||
role,
|
||||
numTrades,
|
||||
privateNotificationManager,
|
||||
|
|
|
@ -25,7 +25,7 @@ import bisq.desktop.components.AutoTooltipLabel;
|
|||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.components.PeerInfoIconTrading;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.ClosedTradesSummaryWindow;
|
||||
|
@ -575,7 +575,7 @@ public class ClosedTradesView extends ActivatableViewAndModel<VBox, ClosedTrades
|
|||
int numPastTrades = model.getNumPastTrades(trade);
|
||||
final NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress();
|
||||
String role = Res.get("peerInfoIcon.tooltip.tradePeer");
|
||||
Node peerInfoIcon = new PeerInfoIcon(tradingPeerNodeAddress,
|
||||
Node peerInfoIcon = new PeerInfoIconTrading(tradingPeerNodeAddress,
|
||||
role,
|
||||
numPastTrades,
|
||||
privateNotificationManager,
|
||||
|
|
|
@ -22,7 +22,7 @@ import bisq.desktop.common.view.ActivatableViewAndModel;
|
|||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.components.PeerInfoIconTrading;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.TradeDetailsWindow;
|
||||
|
@ -828,7 +828,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
|
|||
final NodeAddress tradingPeerNodeAddress = trade.getTradingPeerNodeAddress();
|
||||
int numPastTrades = model.getNumPastTrades(trade);
|
||||
String role = Res.get("peerInfoIcon.tooltip.tradePeer");
|
||||
Node peerInfoIcon = new PeerInfoIcon(tradingPeerNodeAddress,
|
||||
Node peerInfoIcon = new PeerInfoIconTrading(tradingPeerNodeAddress,
|
||||
role,
|
||||
numPastTrades,
|
||||
privateNotificationManager,
|
||||
|
|
|
@ -23,6 +23,8 @@ import bisq.desktop.components.AutoTooltipLabel;
|
|||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.components.PeerInfoIconDispute;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.main.overlays.windows.ContractWindow;
|
||||
import bisq.desktop.main.overlays.windows.DisputeSummaryWindow;
|
||||
|
@ -119,7 +121,7 @@ import javax.annotation.Nullable;
|
|||
import static bisq.desktop.util.FormBuilder.getIconForLabel;
|
||||
import static bisq.desktop.util.FormBuilder.getRegularIconButton;
|
||||
|
||||
public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
||||
public abstract class DisputeView extends ActivatableView<VBox, Void> implements PeerInfoIcon.notify {
|
||||
public enum FilterResult {
|
||||
NO_MATCH("No Match"),
|
||||
NO_FILTER("No filter text"),
|
||||
|
@ -183,6 +185,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
private Map<String, Button> chatButtonByDispute = new HashMap<>();
|
||||
private Map<String, JFXBadge> chatBadgeByDispute = new HashMap<>();
|
||||
private Map<String, JFXBadge> newBadgeByDispute = new HashMap<>();
|
||||
private Map<String, PeerInfoIconDispute> avatarMap = new HashMap<>();
|
||||
protected DisputeChatPopup chatPopup;
|
||||
|
||||
|
||||
|
@ -1183,10 +1186,14 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
@Override
|
||||
public void updateItem(final Dispute item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
if (item != null && !empty) {
|
||||
setText(getBuyerOnionAddressColumnLabel(item));
|
||||
else
|
||||
PeerInfoIconDispute peerInfoIconDispute = findOrCreateAvatar(tableRowProperty().get().getIndex(), item.getContract(), true);
|
||||
setGraphic(peerInfoIconDispute);
|
||||
} else {
|
||||
setText("");
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1209,10 +1216,14 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
@Override
|
||||
public void updateItem(final Dispute item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty)
|
||||
if (item != null && !empty) {
|
||||
setText(getSellerOnionAddressColumnLabel(item));
|
||||
else
|
||||
PeerInfoIconDispute peerInfoIconDispute = findOrCreateAvatar(tableRowProperty().get().getIndex(), item.getContract(), false);
|
||||
setGraphic(peerInfoIconDispute);
|
||||
} else {
|
||||
setText("");
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1230,7 +1241,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
long accountAge = accountAgeWitnessService.getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing());
|
||||
String age = DisplayUtils.formatAccountAge(accountAge);
|
||||
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
|
||||
return buyerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";
|
||||
return buyerNodeAddress.getHostNameForDisplay() + " (" + nrOfDisputes + postFix + ")";
|
||||
} else
|
||||
return Res.get("shared.na");
|
||||
} else {
|
||||
|
@ -1247,7 +1258,7 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
long accountAge = accountAgeWitnessService.getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing());
|
||||
String age = DisplayUtils.formatAccountAge(accountAge);
|
||||
String postFix = CurrencyUtil.isFiatCurrency(item.getContract().getOfferPayload().getCurrencyCode()) ? " / " + age : "";
|
||||
return sellerNodeAddress.getHostNameWithoutPostFix() + " (" + nrOfDisputes + postFix + ")";
|
||||
return sellerNodeAddress.getHostNameForDisplay() + " (" + nrOfDisputes + postFix + ")";
|
||||
} else
|
||||
return Res.get("shared.na");
|
||||
} else {
|
||||
|
@ -1433,4 +1444,31 @@ public abstract class DisputeView extends ActivatableView<VBox, Void> {
|
|||
return (disputeManager instanceof MediationManager) ? Res.get("shared.mediator") : Res.get("shared.refundAgent");
|
||||
}
|
||||
}
|
||||
|
||||
private PeerInfoIconDispute findOrCreateAvatar(Integer tableRowId, Contract contract, boolean isBuyer) {
|
||||
NodeAddress nodeAddress = isBuyer ? contract.getBuyerNodeAddress() : contract.getSellerNodeAddress();
|
||||
String key = tableRowId + nodeAddress.getHostNameWithoutPostFix() + (isBuyer ? "BUYER" : "SELLER");
|
||||
Long accountAge = isBuyer ?
|
||||
accountAgeWitnessService.getAccountAge(contract.getBuyerPaymentAccountPayload(), contract.getBuyerPubKeyRing()) :
|
||||
accountAgeWitnessService.getAccountAge(contract.getSellerPaymentAccountPayload(), contract.getSellerPubKeyRing());
|
||||
PeerInfoIconDispute peerInfoIcon = new PeerInfoIconDispute(
|
||||
nodeAddress,
|
||||
disputeManager.getNrOfDisputes(isBuyer, contract),
|
||||
accountAge,
|
||||
preferences);
|
||||
peerInfoIcon.setCallback(this);
|
||||
avatarMap.put(key, peerInfoIcon);
|
||||
return peerInfoIcon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void avatarTagUpdated() {
|
||||
// callback from one avatar letting us know that the user updated the tag text.
|
||||
// we update all avatars, as some could be sharing the same tag
|
||||
log.info("Updating avatar tags, the avatarMap size is {}", avatarMap.size());
|
||||
avatarMap.forEach((key, avatarIcon) -> {
|
||||
avatarIcon.refreshTag();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,4 +24,10 @@ public class Colors {
|
|||
public static final Paint BLUE = Color.valueOf("#0f87c3");
|
||||
public static final Paint LIGHT_GREY = Color.valueOf("#CCCCCC");
|
||||
public static final Paint GREEN = Color.valueOf("#00aa33");
|
||||
|
||||
public static final Color AVATAR_RED = Color.rgb(255, 0, 0);
|
||||
public static final Color AVATAR_ORANGE = Color.rgb(255, 140, 0);
|
||||
public static final Color AVATAR_BLUE = Color.rgb(0, 139, 205);
|
||||
public static final Color AVATAR_GREEN = Color.rgb(0, 225, 0);
|
||||
public static final Color AVATAR_GREY = Color.rgb(128, 128, 128);
|
||||
}
|
||||
|
|
|
@ -79,6 +79,17 @@ public final class NodeAddress implements PersistablePayload, NetworkPayload, Us
|
|||
return hostName.replace(".onion", "");
|
||||
}
|
||||
|
||||
// tor v3 onions are too long to display for example in a table grid, so this convenience method
|
||||
// produces a display-friendly format which includes [first 7]..[last 7] characters.
|
||||
// tor v2 and localhost will be displayed in full, as they are 16 chars or less.
|
||||
public String getHostNameForDisplay() {
|
||||
String work = getHostNameWithoutPostFix();
|
||||
if (work.length() > 16) {
|
||||
return work.substring(0, 7) + ".." + work.substring(work.length() - 7);
|
||||
}
|
||||
return work;
|
||||
}
|
||||
|
||||
// We use just a few chars from the full address to blur the potential receiver for sent network_messages
|
||||
public byte[] getAddressPrefixHash() {
|
||||
if (addressPrefixHash == null)
|
||||
|
|
Loading…
Add table
Reference in a new issue