mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Add small peer icon (trader icon) to each offer in offer book to emphasize that you are trading with real people on Bisq
This commit is contained in:
parent
a7bf94cc1e
commit
b89320f9b7
5 changed files with 123 additions and 25 deletions
|
@ -55,9 +55,10 @@ public class PeerInfoIcon extends Group {
|
|||
private final Map<String, String> peerTagMap;
|
||||
private final Label numTradesLabel;
|
||||
private final Label tagLabel;
|
||||
private final Pane tagPane;
|
||||
private final Pane numTradesPane;
|
||||
protected final Pane tagPane;
|
||||
protected final Pane numTradesPane;
|
||||
private final String hostName;
|
||||
private final double scaleFactor;
|
||||
|
||||
public PeerInfoIcon(NodeAddress nodeAddress,
|
||||
String role,
|
||||
|
@ -70,6 +71,7 @@ public class PeerInfoIcon extends Group {
|
|||
boolean useDevPrivilegeKeys) {
|
||||
this.numTrades = numTrades;
|
||||
|
||||
scaleFactor = getScaleFactor();
|
||||
hostName = nodeAddress != null ? nodeAddress.getHostName() : "";
|
||||
String address = nodeAddress != null ? nodeAddress.getFullAddress() : "";
|
||||
|
||||
|
@ -108,12 +110,12 @@ public class PeerInfoIcon extends Group {
|
|||
ringColor = Color.rgb(0, 225, 0);
|
||||
}
|
||||
|
||||
double outerSize = 26;
|
||||
double outerSize = 26 * scaleFactor;
|
||||
Canvas outerBackground = new Canvas(outerSize, outerSize);
|
||||
GraphicsContext outerBackgroundGc = outerBackground.getGraphicsContext2D();
|
||||
outerBackgroundGc.setFill(ringColor);
|
||||
outerBackgroundGc.fillOval(0, 0, outerSize, outerSize);
|
||||
outerBackground.setLayoutY(1);
|
||||
outerBackground.setLayoutY(1 * scaleFactor);
|
||||
|
||||
// inner circle
|
||||
int maxIndices = 15;
|
||||
|
@ -138,36 +140,38 @@ public class PeerInfoIcon extends Group {
|
|||
Color innerColor = Color.rgb(red, green, blue);
|
||||
innerColor = innerColor.deriveColor(1, saturation, 0.8, 1); // reduce saturation and brightness
|
||||
|
||||
double innerSize = 22;
|
||||
double innerSize = scaleFactor * 22;
|
||||
Canvas innerBackground = new Canvas(innerSize, innerSize);
|
||||
GraphicsContext innerBackgroundGc = innerBackground.getGraphicsContext2D();
|
||||
innerBackgroundGc.setFill(innerColor);
|
||||
innerBackgroundGc.fillOval(0, 0, innerSize, innerSize);
|
||||
innerBackground.setLayoutY(3);
|
||||
innerBackground.setLayoutX(2);
|
||||
innerBackground.setLayoutY(3 * scaleFactor);
|
||||
innerBackground.setLayoutX(2 * scaleFactor);
|
||||
|
||||
ImageView avatarImageView = new ImageView();
|
||||
avatarImageView.setId("avatar_" + index);
|
||||
avatarImageView.setLayoutX(0);
|
||||
avatarImageView.setLayoutY(1);
|
||||
avatarImageView.setLayoutY(1 * scaleFactor);
|
||||
avatarImageView.setFitHeight(scaleFactor * 26);
|
||||
avatarImageView.setFitWidth(scaleFactor * 26);
|
||||
|
||||
numTradesPane = new Pane();
|
||||
numTradesPane.relocate(18, 14);
|
||||
numTradesPane.relocate(scaleFactor * 18, scaleFactor * 14);
|
||||
numTradesPane.setMouseTransparent(true);
|
||||
ImageView numTradesCircle = new ImageView();
|
||||
numTradesCircle.setId("image-green_circle");
|
||||
numTradesLabel = new AutoTooltipLabel();
|
||||
numTradesLabel.relocate(5, 1);
|
||||
numTradesLabel.relocate(scaleFactor * 5, scaleFactor * 1);
|
||||
numTradesLabel.setId("ident-num-label");
|
||||
numTradesPane.getChildren().addAll(numTradesCircle, numTradesLabel);
|
||||
|
||||
tagPane = new Pane();
|
||||
tagPane.relocate(18, -2);
|
||||
tagPane.relocate(Math.round(scaleFactor * 18), scaleFactor * -2);
|
||||
tagPane.setMouseTransparent(true);
|
||||
ImageView tagCircle = new ImageView();
|
||||
tagCircle.setId("image-blue_circle");
|
||||
tagLabel = new AutoTooltipLabel();
|
||||
tagLabel.relocate(5, 1);
|
||||
tagLabel.relocate(Math.round(scaleFactor * 5), scaleFactor * 1);
|
||||
tagLabel.setId("ident-num-label");
|
||||
tagPane.getChildren().addAll(tagCircle, tagLabel);
|
||||
|
||||
|
@ -175,6 +179,10 @@ public class PeerInfoIcon extends Group {
|
|||
|
||||
getChildren().addAll(outerBackground, innerBackground, avatarImageView, tagPane, numTradesPane);
|
||||
|
||||
addMouseListener(numTrades, privateNotificationManager, offer, preferences, formatter, useDevPrivilegeKeys, isFiatCurrency, makersAccountAge);
|
||||
}
|
||||
|
||||
protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) {
|
||||
final String accountAgeTagEditor = isFiatCurrency ?
|
||||
makersAccountAge > -1 ?
|
||||
formatter.formatAccountAge(makersAccountAge) :
|
||||
|
@ -192,7 +200,11 @@ public class PeerInfoIcon extends Group {
|
|||
.show());
|
||||
}
|
||||
|
||||
private void updatePeerInfoIcon() {
|
||||
protected double getScaleFactor() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
protected void updatePeerInfoIcon() {
|
||||
String tag;
|
||||
if (peerTagMap.containsKey(hostName)) {
|
||||
tag = peerTagMap.get(hostName);
|
||||
|
|
33
src/main/java/bisq/desktop/components/PeerInfoIconSmall.java
Normal file
33
src/main/java/bisq/desktop/components/PeerInfoIconSmall.java
Normal file
|
@ -0,0 +1,33 @@
|
|||
package bisq.desktop.components;
|
||||
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
|
||||
import bisq.core.alert.PrivateNotificationManager;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.payment.AccountAgeWitnessService;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
public class PeerInfoIconSmall extends PeerInfoIcon {
|
||||
public PeerInfoIconSmall(NodeAddress nodeAddress, String role, Offer offer, Preferences preferences, AccountAgeWitnessService accountAgeWitnessService, BSFormatter formatter, boolean useDevPrivilegeKeys) {
|
||||
// We don't want to show number of trades in that case as it would be unreadable.
|
||||
// Also we don't need the privateNotificationManager as no interaction will take place with this icon.
|
||||
super(nodeAddress, role, 0, null, offer, preferences, accountAgeWitnessService, formatter, useDevPrivilegeKeys);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double getScaleFactor() {
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addMouseListener(int numTrades, PrivateNotificationManager privateNotificationManager, Offer offer, Preferences preferences, BSFormatter formatter, boolean useDevPrivilegeKeys, boolean isFiatCurrency, long makersAccountAge) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updatePeerInfoIcon() {
|
||||
numTradesPane.setVisible(false);
|
||||
tagPane.setVisible(false);
|
||||
}
|
||||
}
|
|
@ -24,6 +24,8 @@ import bisq.desktop.components.AutoTooltipButton;
|
|||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.ColoredDecimalPlacesWithZerosText;
|
||||
import bisq.desktop.components.PeerInfoIcon;
|
||||
import bisq.desktop.components.PeerInfoIconSmall;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.offer.BuyOfferView;
|
||||
import bisq.desktop.main.offer.SellOfferView;
|
||||
|
@ -32,15 +34,19 @@ import bisq.desktop.util.BSFormatter;
|
|||
import bisq.desktop.util.CurrencyListItem;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.app.AppOptionKeys;
|
||||
import bisq.core.locale.CurrencyUtil;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
|
||||
import bisq.network.p2p.NodeAddress;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.util.Tuple4;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
import javafx.scene.chart.AreaChart;
|
||||
import javafx.scene.chart.NumberAxis;
|
||||
|
@ -90,6 +96,8 @@ import static bisq.desktop.util.Layout.INITIAL_SCENE_HEIGHT;
|
|||
public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookChartViewModel> {
|
||||
private static final Logger log = LoggerFactory.getLogger(OfferBookChartView.class);
|
||||
|
||||
private final boolean useDevPrivilegeKeys;
|
||||
|
||||
private NumberAxis xAxis;
|
||||
private XYChart.Series seriesBuy, seriesSell;
|
||||
private final Navigation navigation;
|
||||
|
@ -124,10 +132,12 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@Inject
|
||||
public OfferBookChartView(OfferBookChartViewModel model, Navigation navigation, BSFormatter formatter) {
|
||||
public OfferBookChartView(OfferBookChartViewModel model, Navigation navigation, BSFormatter formatter,
|
||||
@Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
|
||||
super(model);
|
||||
this.navigation = navigation;
|
||||
this.formatter = formatter;
|
||||
this.useDevPrivilegeKeys = useDevPrivilegeKeys;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -469,9 +479,49 @@ public class OfferBookChartView extends ActivatableViewAndModel<VBox, OfferBookC
|
|||
}
|
||||
});
|
||||
|
||||
// trader avatar
|
||||
TableColumn<OfferListItem, OfferListItem> avatarColumn = new AutoTooltipTableColumn<OfferListItem, OfferListItem>(Res.get("offerbook.trader")) {
|
||||
{
|
||||
setMinWidth(80);
|
||||
setMaxWidth(80);
|
||||
setSortable(true);
|
||||
}
|
||||
};
|
||||
avatarColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
|
||||
avatarColumn.setCellFactory(
|
||||
new Callback<TableColumn<OfferListItem, OfferListItem>, TableCell<OfferListItem,
|
||||
OfferListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<OfferListItem, OfferListItem> call(TableColumn<OfferListItem, OfferListItem> column) {
|
||||
return new TableCell<OfferListItem, OfferListItem>() {
|
||||
@Override
|
||||
public void updateItem(final OfferListItem newItem, boolean empty) {
|
||||
super.updateItem(newItem, empty);
|
||||
if (newItem != null && !empty) {
|
||||
final Offer offer = newItem.offer;
|
||||
final NodeAddress makersNodeAddress = offer.getOwnerNodeAddress();
|
||||
String role = Res.get("peerInfoIcon.tooltip.maker");
|
||||
PeerInfoIconSmall peerInfoIcon = new PeerInfoIconSmall(makersNodeAddress,
|
||||
role,
|
||||
offer,
|
||||
model.preferences,
|
||||
model.accountAgeWitnessService,
|
||||
formatter,
|
||||
useDevPrivilegeKeys);
|
||||
setGraphic(peerInfoIcon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
tableView.getColumns().add(volumeColumn);
|
||||
tableView.getColumns().add(amountColumn);
|
||||
tableView.getColumns().add(priceColumn);
|
||||
tableView.getColumns().add(avatarColumn);
|
||||
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
Label placeholder = new AutoTooltipLabel(Res.get("table.placeholder.noItems", Res.get("shared.multipleOffers")));
|
||||
|
|
|
@ -35,6 +35,7 @@ import bisq.core.locale.TradeCurrency;
|
|||
import bisq.core.monetary.Price;
|
||||
import bisq.core.offer.Offer;
|
||||
import bisq.core.offer.OfferPayload;
|
||||
import bisq.core.payment.AccountAgeWitnessService;
|
||||
import bisq.core.provider.price.PriceFeedService;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
|
@ -67,6 +68,7 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
private final OfferBook offerBook;
|
||||
final Preferences preferences;
|
||||
final PriceFeedService priceFeedService;
|
||||
final AccountAgeWitnessService accountAgeWitnessService;
|
||||
private final Navigation navigation;
|
||||
|
||||
final ObjectProperty<TradeCurrency> selectedTradeCurrencyProperty = new SimpleObjectProperty<>();
|
||||
|
@ -92,12 +94,13 @@ class OfferBookChartViewModel extends ActivatableViewModel {
|
|||
@SuppressWarnings("WeakerAccess")
|
||||
@Inject
|
||||
public OfferBookChartViewModel(OfferBook offerBook, Preferences preferences, PriceFeedService priceFeedService,
|
||||
Navigation navigation, BSFormatter formatter) {
|
||||
AccountAgeWitnessService accountAgeWitnessService, Navigation navigation, BSFormatter formatter) {
|
||||
this.offerBook = offerBook;
|
||||
this.preferences = preferences;
|
||||
this.priceFeedService = priceFeedService;
|
||||
this.navigation = navigation;
|
||||
this.formatter = formatter;
|
||||
this.accountAgeWitnessService = accountAgeWitnessService;
|
||||
|
||||
Optional<TradeCurrency> tradeCurrencyOptional = CurrencyUtil.getTradeCurrency(preferences.getOfferBookChartScreenCurrencyCode());
|
||||
if (tradeCurrencyOptional.isPresent())
|
||||
|
|
|
@ -64,7 +64,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter());
|
||||
assertEquals(0, model.maxPlacesForBuyPrice.intValue());
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ public class OfferBookChartViewModelTest {
|
|||
when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty());
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(0, model.maxPlacesForBuyPrice.intValue());
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(7, model.maxPlacesForBuyPrice.intValue());
|
||||
offerBookListItems.addAll(make(btcItem.but(with(OfferBookListItemMaker.price, 94016475L))));
|
||||
|
@ -113,7 +113,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter());
|
||||
assertEquals(0, model.maxPlacesForBuyVolume.intValue());
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(4, model.maxPlacesForBuyVolume.intValue()); //0.01
|
||||
offerBookListItems.addAll(make(btcItem.but(with(OfferBookListItemMaker.amount, 100000000L))));
|
||||
|
@ -142,7 +142,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter());
|
||||
assertEquals(0, model.maxPlacesForSellPrice.intValue());
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ public class OfferBookChartViewModelTest {
|
|||
when(priceFeedService.updateCounterProperty()).thenReturn(new SimpleIntegerProperty());
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, priceFeedService, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(0, model.maxPlacesForSellPrice.intValue());
|
||||
}
|
||||
|
@ -175,7 +175,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(7, model.maxPlacesForSellPrice.intValue());
|
||||
offerBookListItems.addAll(make(btcSellItem.but(with(OfferBookListItemMaker.price, 94016475L))));
|
||||
|
@ -191,7 +191,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, null, null, null, new BSFormatter());
|
||||
assertEquals(0, model.maxPlacesForSellVolume.intValue());
|
||||
}
|
||||
|
||||
|
@ -204,7 +204,7 @@ public class OfferBookChartViewModelTest {
|
|||
|
||||
when(offerBook.getOfferBookListItems()).thenReturn(offerBookListItems);
|
||||
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, new BSFormatter());
|
||||
final OfferBookChartViewModel model = new OfferBookChartViewModel(offerBook, empty, service, null, null, new BSFormatter());
|
||||
model.activate();
|
||||
assertEquals(4, model.maxPlacesForSellVolume.intValue()); //0.01
|
||||
offerBookListItems.addAll(make(btcSellItem.but(with(OfferBookListItemMaker.amount, 100000000L))));
|
||||
|
|
Loading…
Add table
Reference in a new issue