diff --git a/gui/src/main/java/io/bitsquare/gui/images.css b/gui/src/main/java/io/bitsquare/gui/images.css index 396135b11a..acd9aa0d46 100644 --- a/gui/src/main/java/io/bitsquare/gui/images.css +++ b/gui/src/main/java/io/bitsquare/gui/images.css @@ -34,7 +34,6 @@ -fx-image: url("../../../images/buy_white.png"); } - #image-sell { -fx-image: url("../../../images/sell.png"); } @@ -213,3 +212,64 @@ -fx-image: url("../../../images/link.png"); } +#avatar_1 { + -fx-image: url("../../../images/avatars/avatar_1.png"); +} + +#avatar_2 { + -fx-image: url("../../../images/avatars/avatar_2.png"); +} + +#avatar_3 { + -fx-image: url("../../../images/avatars/avatar_3.png"); +} + +#avatar_4 { + -fx-image: url("../../../images/avatars/avatar_4.png"); +} + +#avatar_5 { + -fx-image: url("../../../images/avatars/avatar_5.png"); +} + +#avatar_6 { + -fx-image: url("../../../images/avatars/avatar_6.png"); +} + +#avatar_7 { + -fx-image: url("../../../images/avatars/avatar_7.png"); +} + +#avatar_8 { + -fx-image: url("../../../images/avatars/avatar_8.png"); +} + +#avatar_9 { + -fx-image: url("../../../images/avatars/avatar_9.png"); +} + +#avatar_10 { + -fx-image: url("../../../images/avatars/avatar_10.png"); +} + +#avatar_11 { + -fx-image: url("../../../images/avatars/avatar_11.png"); +} + +#avatar_12 { + -fx-image: url("../../../images/avatars/avatar_12.png"); +} + +#avatar_13 { + -fx-image: url("../../../images/avatars/avatar_13.png"); +} + +#avatar_14 { + -fx-image: url("../../../images/avatars/avatar_14.png"); +} + +#avatar_15 { + -fx-image: url("../../../images/avatars/avatar_15.png"); +} + + diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java index 8eb607867b..96623177e4 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookView.java @@ -32,6 +32,7 @@ import io.bitsquare.gui.main.funds.withdrawal.WithdrawalView; import io.bitsquare.gui.main.offer.OfferView; import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow; +import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.gui.util.Layout; import io.bitsquare.locale.BSResources; import io.bitsquare.locale.CryptoCurrency; @@ -43,6 +44,7 @@ import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.geometry.HPos; import javafx.geometry.Insets; import javafx.geometry.VPos; +import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.image.ImageView; import javafx.scene.layout.GridPane; @@ -153,6 +155,7 @@ public class OfferBookView extends ActivatableViewAndModel model.onSetPaymentMethod(paymentMethodComboBox.getSelectionModel().getSelectedItem())); createOfferButton.setOnAction(e -> onCreateOffer()); - priceColumn.textProperty().bind(createStringBinding( - () -> !model.showAllTradeCurrenciesProperty.get() ? - "Price in " + model.tradeCurrencyCode.get() + "/BTC" : - "Price", - model.tradeCurrencyCode, - model.showAllTradeCurrenciesProperty)); - volumeColumn.textProperty().bind(createStringBinding( - () -> !model.showAllTradeCurrenciesProperty.get() ? - "Amount in " + model.tradeCurrencyCode.get() + " (Min.)" : - "Amount (Min.)", + () -> { + setDirectionTitles(); + String tradeCurrencyCode = model.tradeCurrencyCode.get(); + boolean showAllTradeCurrencies = model.showAllTradeCurrenciesProperty.get(); + priceColumn.setText(!showAllTradeCurrencies ? + "Price in " + tradeCurrencyCode + "/BTC" : + "Price"); + return !showAllTradeCurrencies ? + "Amount in " + tradeCurrencyCode + " (Min.)" : + "Amount (Min.)"; + }, model.tradeCurrencyCode, model.showAllTradeCurrenciesProperty)); @@ -212,6 +216,7 @@ public class OfferBookView extends ActivatableViewAndModel getAvatarColumn() { + TableColumn column = new TableColumn("") { + { + setMinWidth(32); + setMaxWidth(32); + setSortable(true); + } + }; + column.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + column.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + @Override + public void updateItem(final OfferBookListItem newItem, boolean empty) { + super.updateItem(newItem, empty); + + if (newItem != null && !empty) { + String hostName = newItem.getOffer().getOwnerNodeAddress().hostName; + int numPastTrades = model.getNumPastTrades(newItem.getOffer()); + boolean hasTraded = numPastTrades > 0; + String tooltipText = hasTraded ? "Offerers onion address: " + hostName + "\n" + + "You have already traded " + numPastTrades + " times with that offerer." : "Offerers onion address: " + hostName; + Node identIcon = ImageUtil.getIdentIcon(hostName, tooltipText, hasTraded); + if (identIcon != null) + setGraphic(identIcon); + } else { + setGraphic(null); + } + } + }; + } + }); + return column; + } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java index e04bade28d..0b94c7b1a6 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/offer/offerbook/OfferBookViewModel.java @@ -33,6 +33,8 @@ import io.bitsquare.locale.*; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.P2PService; import io.bitsquare.payment.*; +import io.bitsquare.trade.Trade; +import io.bitsquare.trade.closed.ClosedTradableManager; import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.OpenOfferManager; import io.bitsquare.user.Preferences; @@ -69,6 +71,7 @@ class OfferBookViewModel extends ActivatableViewModel { private final Preferences preferences; private final P2PService p2PService; private final PriceFeed priceFeed; + private ClosedTradableManager closedTradableManager; private Navigation navigation; final BSFormatter formatter; @@ -101,6 +104,7 @@ class OfferBookViewModel extends ActivatableViewModel { @Inject public OfferBookViewModel(User user, OpenOfferManager openOfferManager, OfferBook offerBook, Preferences preferences, P2PService p2PService, PriceFeed priceFeed, + ClosedTradableManager closedTradableManager, Navigation navigation, BSFormatter formatter) { super(); @@ -110,6 +114,7 @@ class OfferBookViewModel extends ActivatableViewModel { this.preferences = preferences; this.p2PService = p2PService; this.priceFeed = priceFeed; + this.closedTradableManager = closedTradableManager; this.navigation = navigation; this.formatter = formatter; @@ -435,4 +440,12 @@ class OfferBookViewModel extends ActivatableViewModel { private boolean isEditEntry(String id) { return id.equals(EDIT_FLAG); } + + public int getNumPastTrades(Offer offer) { + return closedTradableManager.getClosedTrades().stream() + .filter(e -> e instanceof Trade && ((Trade) e).getTradingPeerNodeAddress() != null && + ((Trade) e).getTradingPeerNodeAddress().hostName.equals(offer.getOffererNodeAddress().hostName)) + .collect(Collectors.toSet()) + .size(); + } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.fxml b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.fxml index 54b6368eb3..80f4352538 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.fxml @@ -35,6 +35,7 @@ + diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.java index e69dfcc45c..69b1f7f66b 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/closedtrades/ClosedTradesView.java @@ -23,11 +23,13 @@ import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.main.overlays.windows.OfferDetailsWindow; import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow; import io.bitsquare.gui.util.BSFormatter; +import io.bitsquare.gui.util.ImageUtil; import io.bitsquare.trade.Tradable; import io.bitsquare.trade.Trade; import io.bitsquare.trade.offer.OpenOffer; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.fxml.FXML; +import javafx.scene.Node; import javafx.scene.control.*; import javafx.scene.layout.VBox; import javafx.util.Callback; @@ -41,7 +43,7 @@ public class ClosedTradesView extends ActivatableViewAndModel table; @FXML TableColumn priceColumn, amountColumn, volumeColumn, - directionColumn, dateColumn, tradeIdColumn, stateColumn; + directionColumn, dateColumn, tradeIdColumn, stateColumn, avatarColumn; private final BSFormatter formatter; private final OfferDetailsWindow offerDetailsWindow; private final TradeDetailsWindow tradeDetailsWindow; @@ -63,6 +65,7 @@ public class ClosedTradesView extends ActivatableViewAndModel setAvatarColumnCellFactory() { + avatarColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + avatarColumn.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + @Override + public void updateItem(final ClosedTradableListItem newItem, boolean empty) { + super.updateItem(newItem, empty); + + if (newItem != null && !empty && newItem.getTradable() instanceof Trade) { + + String hostName = ((Trade) newItem.getTradable()).getTradingPeerNodeAddress().hostName; + Node identIcon = ImageUtil.getIdentIcon(hostName, "Trading peers onion address: " + hostName, true); + if (identIcon != null) + setGraphic(identIcon); + } else { + setGraphic(null); + } + } + }; + } + }); + return avatarColumn; + } private void setAmountColumnCellFactory() { amountColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml index eb36e40ed5..21b3927083 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.fxml @@ -52,6 +52,7 @@ + diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java index 4e37790bc6..73e6a41453 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesView.java @@ -25,9 +25,11 @@ import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.main.overlays.windows.TradeDetailsWindow; import io.bitsquare.gui.util.BSFormatter; +import io.bitsquare.gui.util.ImageUtil; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.event.EventHandler; import javafx.fxml.FXML; +import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.TextFieldTableCell; @@ -56,7 +58,7 @@ public class PendingTradesView extends ActivatableViewAndModel priceColumn, tradeVolumeColumn; @FXML - TableColumn roleColumn, paymentMethodColumn, idColumn, dateColumn; + TableColumn avatarColumn, roleColumn, paymentMethodColumn, idColumn, dateColumn; @FXML TableColumn tradeAmountColumn; @@ -88,6 +90,7 @@ public class PendingTradesView extends ActivatableViewAndModel setAvatarColumnCellFactory() { + avatarColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue())); + avatarColumn.setCellFactory( + new Callback, TableCell>() { + + @Override + public TableCell call(TableColumn column) { + return new TableCell() { + @Override + public void updateItem(final PendingTradesListItem newItem, boolean empty) { + super.updateItem(newItem, empty); + + if (newItem != null && !empty && newItem.getTrade().getTradingPeerNodeAddress() != null) { + String hostName = newItem.getTrade().getTradingPeerNodeAddress().hostName; + int numPastTrades = model.getNumPastTrades(newItem.getTrade()); + boolean hasTraded = numPastTrades > 0; + String tooltipText = hasTraded ? "Trading peers onion address: " + hostName + "\n" + + "You have already traded " + numPastTrades + " times with that peer." : "Trading peers onion address: " + hostName; + Node identIcon = ImageUtil.getIdentIcon(hostName, tooltipText, hasTraded); + if (identIcon != null) + setGraphic(identIcon); + } else { + setGraphic(null); + } + } + }; + } + }); + return avatarColumn; + } } diff --git a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java index 3b45bc3d64..ca9dfa1c10 100644 --- a/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java +++ b/gui/src/main/java/io/bitsquare/gui/main/portfolio/pendingtrades/PendingTradesViewModel.java @@ -30,6 +30,7 @@ import io.bitsquare.p2p.P2PService; import io.bitsquare.payment.PaymentMethod; import io.bitsquare.trade.Contract; import io.bitsquare.trade.Trade; +import io.bitsquare.trade.closed.ClosedTradableManager; import io.bitsquare.trade.offer.Offer; import io.bitsquare.user.User; import javafx.beans.property.*; @@ -38,6 +39,8 @@ import org.bitcoinj.core.BlockChainListener; import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.Subscription; +import java.util.stream.Collectors; + import static io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesViewModel.SellerState.*; public class PendingTradesViewModel extends ActivatableWithDataModel implements ViewModel { @@ -70,6 +73,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel buyerState = new SimpleObjectProperty<>(); @@ -88,6 +92,7 @@ public class PendingTradesViewModel extends ActivatableWithDataModel e instanceof Trade && ((Trade) e).getTradingPeerNodeAddress() != null && + ((Trade) e).getTradingPeerNodeAddress().hostName.equals(trade.getTradingPeerNodeAddress().hostName)) + .collect(Collectors.toSet()) + .size(); + } /////////////////////////////////////////////////////////////////////////////////////////// // States diff --git a/gui/src/main/java/io/bitsquare/gui/util/ImageUtil.java b/gui/src/main/java/io/bitsquare/gui/util/ImageUtil.java index 1469fbdfbd..4a12735831 100644 --- a/gui/src/main/java/io/bitsquare/gui/util/ImageUtil.java +++ b/gui/src/main/java/io/bitsquare/gui/util/ImageUtil.java @@ -19,11 +19,21 @@ package io.bitsquare.gui.util; import com.sun.javafx.tk.quantum.QuantumToolkit; import io.bitsquare.locale.Country; +import javafx.scene.Group; +import javafx.scene.Node; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Tooltip; import javafx.scene.image.Image; import javafx.scene.image.ImageView; +import javafx.scene.paint.Color; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.UUID; + public class ImageUtil { private static final Logger log = LoggerFactory.getLogger(ImageUtil.class); @@ -55,6 +65,71 @@ public class ImageUtil { } public static boolean isRetina() { - return ((QuantumToolkit) QuantumToolkit.getToolkit()).getMaxRenderScale() > 1.9f; + float maxRenderScale = ((QuantumToolkit) QuantumToolkit.getToolkit()).getMaxRenderScale(); + boolean isRetina = maxRenderScale > 1.9f; + log.info("isRetina=" + isRetina + " / maxRenderScale=" + maxRenderScale); + return isRetina; + } + + public static Node getIdentIcon(String hostName, String tooltipText, boolean hasTraded) { + if (!hostName.isEmpty()) { + // for testing locally we use a random hostname to get dif. colors + if (hostName.startsWith("localhost")) + hostName = UUID.randomUUID().toString().replace("-", "").substring(0, 16); + + int maxIndices = 15; + try { + MessageDigest md = MessageDigest.getInstance("SHA1"); + byte[] bytes = md.digest(hostName.getBytes()); + int intValue = Math.abs(((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) + | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF)); + + int index = (intValue % maxIndices) + 1; + + int red = intValue % 256; + int green = (intValue >> 8) % 64; // we use green for marking repeated trades, so avoid it in main bg color + int blue = (intValue >> 16) % 256; + + ImageView iconView = new ImageView(); + iconView.setId("avatar_" + index); + iconView.setScaleX(intValue % 2 == 0 ? 1d : -1d); + double size = 26; + Group iconGroup = new Group(); + + Color color = Color.rgb(red, green, blue); + color = color.deriveColor(1, 0.6, 1, 1); // reduce saturation + + if (hasTraded) { + Canvas outerBg = new Canvas(size, size); + GraphicsContext gc = outerBg.getGraphicsContext2D(); + gc.setFill(Color.rgb(0, 170, 51)); // green + gc.fillOval(0, 0, size, size); + outerBg.setLayoutY(1); + + Canvas innerBg = new Canvas(size, size); + GraphicsContext gc2 = innerBg.getGraphicsContext2D(); + gc2.setFill(color); + gc2.fillOval(2, 2, size - 4, size - 4); + innerBg.setLayoutY(1); + iconGroup.getChildren().addAll(outerBg, innerBg, iconView); + } else { + Canvas bg = new Canvas(size, size); + GraphicsContext gc = bg.getGraphicsContext2D(); + gc.setFill(color); + gc.fillOval(0, 0, size, size); + bg.setLayoutY(1); + iconGroup.getChildren().addAll(bg, iconView); + } + + Tooltip.install(iconGroup, new Tooltip(tooltipText)); + return iconGroup; + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + log.error(e.toString()); + return null; + } + } else { + return null; + } } } diff --git a/gui/src/main/resources/images/avatars/avatar_1.png b/gui/src/main/resources/images/avatars/avatar_1.png new file mode 100644 index 0000000000..32fa7c4bca Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_1.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_10.png b/gui/src/main/resources/images/avatars/avatar_10.png new file mode 100644 index 0000000000..7318cbac98 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_10.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_10@2x.png b/gui/src/main/resources/images/avatars/avatar_10@2x.png new file mode 100644 index 0000000000..14f07e3438 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_10@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_11.png b/gui/src/main/resources/images/avatars/avatar_11.png new file mode 100644 index 0000000000..6e3a75b441 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_11.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_11@2x.png b/gui/src/main/resources/images/avatars/avatar_11@2x.png new file mode 100644 index 0000000000..7900ece8a3 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_11@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_12.png b/gui/src/main/resources/images/avatars/avatar_12.png new file mode 100644 index 0000000000..cd4ad9f4e5 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_12.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_12@2x.png b/gui/src/main/resources/images/avatars/avatar_12@2x.png new file mode 100644 index 0000000000..3e5e20937a Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_12@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_13.png b/gui/src/main/resources/images/avatars/avatar_13.png new file mode 100644 index 0000000000..37be4f4827 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_13.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_13@2x.png b/gui/src/main/resources/images/avatars/avatar_13@2x.png new file mode 100644 index 0000000000..55f3b92511 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_13@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_14.png b/gui/src/main/resources/images/avatars/avatar_14.png new file mode 100644 index 0000000000..4d971e0340 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_14.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_14@2x.png b/gui/src/main/resources/images/avatars/avatar_14@2x.png new file mode 100644 index 0000000000..d0f000def1 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_14@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_15.png b/gui/src/main/resources/images/avatars/avatar_15.png new file mode 100644 index 0000000000..b4081c7b21 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_15.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_15@2x.png b/gui/src/main/resources/images/avatars/avatar_15@2x.png new file mode 100644 index 0000000000..1343867ead Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_15@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_1@2x.png b/gui/src/main/resources/images/avatars/avatar_1@2x.png new file mode 100644 index 0000000000..43e3b59d42 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_1@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_2.png b/gui/src/main/resources/images/avatars/avatar_2.png new file mode 100644 index 0000000000..8436f2c08d Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_2.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_2@2x.png b/gui/src/main/resources/images/avatars/avatar_2@2x.png new file mode 100644 index 0000000000..75e30792a6 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_2@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_3.png b/gui/src/main/resources/images/avatars/avatar_3.png new file mode 100644 index 0000000000..7049db346f Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_3.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_3@2x.png b/gui/src/main/resources/images/avatars/avatar_3@2x.png new file mode 100644 index 0000000000..e6a4e25118 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_3@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_4.png b/gui/src/main/resources/images/avatars/avatar_4.png new file mode 100644 index 0000000000..f327e685d4 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_4.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_4@2x.png b/gui/src/main/resources/images/avatars/avatar_4@2x.png new file mode 100644 index 0000000000..edc4f0ce49 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_4@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_5.png b/gui/src/main/resources/images/avatars/avatar_5.png new file mode 100644 index 0000000000..7f0d0e18a5 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_5.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_5@2x.png b/gui/src/main/resources/images/avatars/avatar_5@2x.png new file mode 100644 index 0000000000..ea4ba4aaa6 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_5@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_6.png b/gui/src/main/resources/images/avatars/avatar_6.png new file mode 100644 index 0000000000..b5afc8f784 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_6.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_6@2x.png b/gui/src/main/resources/images/avatars/avatar_6@2x.png new file mode 100644 index 0000000000..deee9ebdac Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_6@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_7.png b/gui/src/main/resources/images/avatars/avatar_7.png new file mode 100644 index 0000000000..42c15441c0 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_7.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_7@2x.png b/gui/src/main/resources/images/avatars/avatar_7@2x.png new file mode 100644 index 0000000000..1dfc5520bc Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_7@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_8.png b/gui/src/main/resources/images/avatars/avatar_8.png new file mode 100644 index 0000000000..8d49bcb0a8 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_8.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_8@2x.png b/gui/src/main/resources/images/avatars/avatar_8@2x.png new file mode 100644 index 0000000000..e2989065b0 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_8@2x.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_9.png b/gui/src/main/resources/images/avatars/avatar_9.png new file mode 100644 index 0000000000..398f4ffb1a Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_9.png differ diff --git a/gui/src/main/resources/images/avatars/avatar_9@2x.png b/gui/src/main/resources/images/avatars/avatar_9@2x.png new file mode 100644 index 0000000000..4c0720cb96 Binary files /dev/null and b/gui/src/main/resources/images/avatars/avatar_9@2x.png differ