Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce payment columns in offerbook listview #2559

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,22 @@

import bisq.common.data.Triple;
import bisq.desktop.common.Layout;
import bisq.desktop.common.utils.ImageUtil;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;

import java.util.Random;

public class BisqEasyViewUtils {
private static final String[] customPaymentIconIds = {"CUSTOM_PAYMENT_1", "CUSTOM_PAYMENT_2", "CUSTOM_PAYMENT_3"};
private static final Random random = new Random();

public static Triple<Label, HBox, VBox> getContainer(String headline, Node content) {
Label headlineLabel = new Label(headline);
headlineLabel.getStyleClass().add("bisq-easy-container-headline");
Expand All @@ -43,4 +51,18 @@ public static Triple<Label, HBox, VBox> getContainer(String headline, Node conte

return new Triple<>(headlineLabel, header, vBox);
}
}

public static StackPane getCustomPaymentMethodIcon(String customPaymentMethod) {
char initial = customPaymentMethod.charAt(0);

Label initialLabel = new Label(String.valueOf(initial));
initialLabel.getStyleClass().add("bisq-easy-custom-payment-icon");

int iconIndex = random.nextInt(customPaymentIconIds.length);
ImageView customPaymentIcon = ImageUtil.getImageViewById(customPaymentIconIds[iconIndex]);

StackPane stackPane = new StackPane(customPaymentIcon, initialLabel);
stackPane.setAlignment(Pos.CENTER);
return stackPane;
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package bisq.desktop.main.content.bisq_easy.offerbook;

import bisq.account.payment_method.BitcoinPaymentMethod;
import bisq.account.payment_method.FiatPaymentMethod;
import bisq.common.currency.Market;
import bisq.common.currency.MarketRepository;
import bisq.desktop.common.utils.ImageUtil;
import bisq.desktop.components.containers.Spacer;
import bisq.desktop.components.controls.Badge;
import bisq.desktop.components.controls.BisqTooltip;
import bisq.desktop.main.content.bisq_easy.BisqEasyViewUtils;
import bisq.desktop.main.content.components.ReputationScoreDisplay;
import bisq.desktop.main.content.components.UserProfileIcon;
import bisq.i18n.Res;
Expand Down Expand Up @@ -276,4 +279,61 @@ protected void updateItem(OfferMessageItem item, boolean empty) {
}
};
}

static Callback<TableColumn<OfferMessageItem, OfferMessageItem>,
TableCell<OfferMessageItem, OfferMessageItem>> getOfferMessagePaymentCellFactory() {
return column -> new TableCell<>() {
@Override
protected void updateItem(OfferMessageItem item, boolean empty) {
super.updateItem(item, empty);

if (item != null && !empty) {
HBox hbox = new HBox(5);
hbox.setAlignment(Pos.CENTER_LEFT);
for (FiatPaymentMethod fiatPaymentMethod : item.getFiatPaymentMethods()) {
Label label = new Label();
Node paymentMethodIcon = !fiatPaymentMethod.isCustomPaymentMethod()
? ImageUtil.getImageViewById(fiatPaymentMethod.getName())
: BisqEasyViewUtils.getCustomPaymentMethodIcon(fiatPaymentMethod.getDisplayString().toUpperCase());
label.setGraphic(paymentMethodIcon);
BisqTooltip tooltip = new BisqTooltip();
tooltip.getStyleClass().add("medium-dark-tooltip");
tooltip.setText(fiatPaymentMethod.getDisplayString());
Tooltip.install(label, tooltip);
hbox.getChildren().add(label);
}
setGraphic(hbox);
} else {
setGraphic(null);
}
}
};
}

static Callback<TableColumn<OfferMessageItem, OfferMessageItem>,
TableCell<OfferMessageItem, OfferMessageItem>> getOfferMessageSettlementCellFactory() {
return column -> new TableCell<>() {
@Override
protected void updateItem(OfferMessageItem item, boolean empty) {
super.updateItem(item, empty);

if (item != null && !empty) {
HBox hbox = new HBox(5);
hbox.setAlignment(Pos.CENTER_LEFT);
for (BitcoinPaymentMethod bitcoinPaymentMethod : item.getBitcoinPaymentMethods()) {
Label label = new Label();
label.setGraphic(ImageUtil.getImageViewById(bitcoinPaymentMethod.getName()));
BisqTooltip tooltip = new BisqTooltip();
tooltip.getStyleClass().add("medium-dark-tooltip");
tooltip.setText(bitcoinPaymentMethod.getDisplayString());
Tooltip.install(label, tooltip);
hbox.getChildren().add(label);
}
setGraphic(hbox);
} else {
setGraphic(null);
}
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
public final class BisqEasyOfferbookView extends ChatView<BisqEasyOfferbookView, BisqEasyOfferbookModel> {
private static final String BUY_FROM_MENU_ITEM_STYLE_CLASS = "buy-from-offers";
private static final String SELL_TO_MENU_ITEM_STYLE_CLASS = "sell-to-offers";
private static final double EXPANDED_OFFER_LIST_WIDTH = 438;
private static final double EXPANDED_OFFER_LIST_WIDTH = 678;
private static final double EXPANDED_MARKET_SELECTION_LIST_WIDTH = 210;
private static final double COLLAPSED_LIST_WIDTH = 40;

Expand Down Expand Up @@ -683,11 +683,30 @@ private void configOffersTableView(BisqTableView<OfferMessageItem> tableView) {
.isSortable(true)
.build();

BisqTableColumn<OfferMessageItem> paymentTableColumn = new BisqTableColumn.Builder<OfferMessageItem>()
.title(Res.get("bisqEasy.offerbook.offerList.table.columns.paymentMethod"))
.left()
.fixWidth(120)
.setCellFactory(BisqEasyOfferbookUtil.getOfferMessagePaymentCellFactory())
.isSortable(false)
.build();

BisqTableColumn<OfferMessageItem> settlementTableColumn = new BisqTableColumn.Builder<OfferMessageItem>()
.title(Res.get("bisqEasy.offerbook.offerList.table.columns.settlementMethod"))
.left()
.fixWidth(120)
.setCellFactory(BisqEasyOfferbookUtil.getOfferMessageSettlementCellFactory())
.comparator(Comparator.comparing(OfferMessageItem::getBitcoinPaymentMethodsAsString))
.isSortable(true)
.build();

tableView.getColumns().add(tableView.getSelectionMarkerColumn());
tableView.getColumns().add(userProfileTableColumn);
tableView.getColumns().add(priceTableColumn);
tableView.getColumns().add(spacerColumn);
tableView.getColumns().add(fiatAmountTableColumn);
tableView.getColumns().add(paymentTableColumn);
tableView.getColumns().add(settlementTableColumn);

tableView.getSortOrder().add(userProfileTableColumn);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
public class MarketChannelItem {
private static final ColorAdjust DEFAULT_COLOR_ADJUST = new ColorAdjust();
private static final ColorAdjust SELECTED_COLOR_ADJUST = new ColorAdjust();
public static final String ASTERISK_SYMBOL = "\u002A"; // Unicode for "*"

@EqualsAndHashCode.Include
private final BisqEasyOfferbookChannel channel;
Expand Down Expand Up @@ -101,7 +102,7 @@ private void applyNotification(ChatNotification notification) {
if (numNotifications > 9) {
// We don't have enough space for 2-digit numbers, so we show an asterix. Standard asterix would not be
// centered, thus we use the `full width asterisk` taken from https://www.piliapp.com/symbol/asterisk/
value = "*";
value = ASTERISK_SYMBOL;
} else if (numNotifications > 0) {
value = String.valueOf(numNotifications);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

package bisq.desktop.main.content.bisq_easy.offerbook;

import bisq.account.payment_method.BitcoinPaymentMethod;
import bisq.account.payment_method.FiatPaymentMethod;
import bisq.bonded_roles.market_price.MarketPriceService;
import bisq.chat.bisqeasy.offerbook.BisqEasyOfferbookMessage;
import bisq.common.data.Pair;
Expand All @@ -27,6 +29,7 @@
import bisq.offer.amount.OfferAmountFormatter;
import bisq.offer.amount.OfferAmountUtil;
import bisq.offer.bisq_easy.BisqEasyOffer;
import bisq.offer.payment_method.PaymentMethodSpecUtil;
import bisq.offer.price.PriceUtil;
import bisq.presentation.formatters.TimeFormatter;
import bisq.user.profile.UserProfile;
Expand All @@ -39,6 +42,9 @@
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.Comparator;
import java.util.List;

@Slf4j
@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
Expand All @@ -55,6 +61,9 @@ public class OfferMessageItem {
private final long lastSeen;
private final String lastSeenAsString;
private final ObjectProperty<ReputationScore> reputationScore = new SimpleObjectProperty<>();
private final List<FiatPaymentMethod> fiatPaymentMethods;
private final List<BitcoinPaymentMethod> bitcoinPaymentMethods;
private final String bitcoinPaymentMethodsAsString;
private long totalScore;
private double priceSpecAsPercent;
private Pin marketPriceByCurrencyMapPin, reputationChangedPin;
Expand All @@ -65,10 +74,13 @@ public class OfferMessageItem {
MarketPriceService marketPriceService,
UserProfileService userProfileService) {
this.bisqEasyOfferbookMessage = bisqEasyOfferbookMessage;
this.bisqEasyOffer = bisqEasyOfferbookMessage.getBisqEasyOffer().orElseThrow();
bisqEasyOffer = bisqEasyOfferbookMessage.getBisqEasyOffer().orElseThrow();
this.userProfile = userProfile;
this.reputationService = reputationService;
this.marketPriceService = marketPriceService;
fiatPaymentMethods = retrieveAndSortFiatPaymentMethods();
bitcoinPaymentMethods = retrieveAndSortBitcoinPaymentMethods();
bitcoinPaymentMethodsAsString = createBitcoinPaymentMethodsAsString();
userNickname = userProfile.getNickName();
minMaxAmount = retrieveMinMaxAmount();
minMaxAmountAsString = OfferAmountFormatter.formatQuoteAmount(marketPriceService, bisqEasyOffer, false);
Expand Down Expand Up @@ -115,4 +127,28 @@ private void updateReputationScore() {
reputationScore.set(reputationService.getReputationScore(userProfile));
totalScore = reputationScore.get().getTotalScore();
}

private List<FiatPaymentMethod> retrieveAndSortFiatPaymentMethods() {
List<FiatPaymentMethod> paymentMethods =
PaymentMethodSpecUtil.getPaymentMethods(bisqEasyOffer.getQuoteSidePaymentMethodSpecs());
paymentMethods.sort(Comparator.comparing(FiatPaymentMethod::isCustomPaymentMethod)
.thenComparing(FiatPaymentMethod::getDisplayString));
return paymentMethods;
}

private List<BitcoinPaymentMethod> retrieveAndSortBitcoinPaymentMethods() {
List<BitcoinPaymentMethod> paymentMethods =
PaymentMethodSpecUtil.getPaymentMethods(bisqEasyOffer.getBaseSidePaymentMethodSpecs());
paymentMethods.sort(Comparator.comparing(BitcoinPaymentMethod::getDisplayString).reversed());
return paymentMethods;
}

private String createBitcoinPaymentMethodsAsString() {
StringBuilder builder = new StringBuilder();
for (BitcoinPaymentMethod bitcoinPaymentMethod : bitcoinPaymentMethods) {
builder.append(bitcoinPaymentMethod.getDisplayString());
builder.append(", ");
}
return builder.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import javafx.geometry.Insets;
import javafx.geometry.Point2D;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
Expand Down Expand Up @@ -481,8 +482,10 @@ public void updateItem(final ListItem item, boolean empty) {
super.updateItem(item, empty);

if (item != null && !empty) {
ImageView icon = ImageUtil.getImageViewById(item.getFiatPaymentRail().name());
StackPane pane = new StackPane(icon);
Node paymentMethodIcon = !item.isFiatPaymentMethodCustom()
? ImageUtil.getImageViewById(item.getFiatPaymentRail().name())
: BisqEasyViewUtils.getCustomPaymentMethodIcon(item.getFiatPaymentMethod().toUpperCase());
StackPane pane = new StackPane(paymentMethodIcon);
pane.setAlignment(Pos.CENTER_RIGHT);
tooltip.setText(Res.get("bisqEasy.openTrades.table.paymentMethod.tooltip",
item.getFiatPaymentMethod()));
Expand Down Expand Up @@ -552,6 +555,7 @@ static class ListItem implements DateTableItem {
private final long myselfLastSeen, peerLastSeen;
private final BitcoinPaymentRail bitcoinPaymentRail;
private final FiatPaymentRail fiatPaymentRail;
private final boolean isFiatPaymentMethodCustom;

private long peerNumNotifications, mediatorNumNotifications;
private String mediatorUserName = "";
Expand Down Expand Up @@ -590,6 +594,7 @@ public ListItem(BisqEasyOpenTradeChannel channel,
fiatPaymentRail = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().getPaymentRail();
bitcoinSettlementMethod = contract.getBaseSidePaymentMethodSpec().getShortDisplayString();
fiatPaymentMethod = contract.getQuoteSidePaymentMethodSpec().getShortDisplayString();
isFiatPaymentMethodCustom = contract.getQuoteSidePaymentMethodSpec().getPaymentMethod().isCustomPaymentMethod();

myRole = BisqEasyTradeFormatter.getMakerTakerRole(trade);
reputationScore = reputationService.getReputationScore(peersUserProfile);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@
import bisq.desktop.common.view.View;
import bisq.desktop.components.containers.Spacer;
import bisq.desktop.components.controls.ChipToggleButton;
import bisq.desktop.main.content.bisq_easy.BisqEasyViewUtils;
import bisq.offer.payment_method.BitcoinPaymentMethodSpec;
import bisq.offer.payment_method.FiatPaymentMethodSpec;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleGroup;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -103,10 +106,10 @@ protected void onViewAttached() {
for (FiatPaymentMethodSpec spec : model.getSortedFiatPaymentMethodSpecs()) {
FiatPaymentMethod paymentMethod = spec.getPaymentMethod();
ChipToggleButton chipToggleButton = new ChipToggleButton(paymentMethod.getShortDisplayString(), fiatToggleGroup);
if (!paymentMethod.isCustomPaymentMethod()) {
ImageView icon = ImageUtil.getImageViewById(paymentMethod.getName());
chipToggleButton.setLeftIcon(icon);
}
Node icon = !paymentMethod.isCustomPaymentMethod()
? ImageUtil.getImageViewById(paymentMethod.getName())
: BisqEasyViewUtils.getCustomPaymentMethodIcon(paymentMethod.getDisplayString());
chipToggleButton.setLeftIcon(icon);
chipToggleButton.setOnAction(() -> controller.onToggleFiatPaymentMethod(spec, chipToggleButton.isSelected()));
chipToggleButton.setSelected(spec.equals(model.getSelectedFiatPaymentMethodSpec().get()));
fiatGridPane.add(chipToggleButton, col++, row);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,15 @@
import bisq.desktop.components.containers.Spacer;
import bisq.desktop.components.controls.BisqTooltip;
import bisq.desktop.components.controls.ChipButton;
import bisq.desktop.main.content.bisq_easy.BisqEasyViewUtils;
import bisq.i18n.Res;
import javafx.collections.ListChangeListener;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.TextAlignment;
import lombok.extern.slf4j.Slf4j;
Expand Down Expand Up @@ -177,6 +179,8 @@ private void setUpAndFillFiatPaymentMethods() {
customMethod -> {
ImageView closeIcon = chipButton.setRightIcon("remove-white");
closeIcon.setOnMousePressed(e -> controller.onRemoveFiatCustomMethod(fiatPaymentMethod));
StackPane icon = BisqEasyViewUtils.getCustomPaymentMethodIcon(customMethod.getDisplayString());
chipButton.setLeftIcon(icon);
},
() -> {
// Lookup for an image with the id of the enum name (REVOLUT)
Expand Down
7 changes: 7 additions & 0 deletions apps/desktop/desktop/src/main/resources/css/bisq_easy.css
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,13 @@
-fx-text-fill: -fx-light-text-color;
}

.bisq-easy-custom-payment-icon .text {
-fx-font-size: 1.2em;
-fx-font-family: "IBM Plex Sans Bold";
-fx-text-fill: -fx-dark-text-color !important;
-fx-fill: -fx-dark-text-color !important;
}


/*******************************************************************************
* *
Expand Down
12 changes: 12 additions & 0 deletions apps/desktop/desktop/src/main/resources/css/images.css
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,18 @@
-fx-image: url("/images/payment/cashapp-.png");
}

#CUSTOM_PAYMENT_1 {
-fx-image: url("/images/payment/custom-payment-1.png");
}

#CUSTOM_PAYMENT_2 {
-fx-image: url("/images/payment/custom-payment-2.png");
}

#CUSTOM_PAYMENT_3 {
-fx-image: url("/images/payment/custom-payment-3.png");
}

#add-custom-green {
-fx-image: url("/images/payment/add-custom-green.png");
}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions i18n/src/main/resources/bisq_easy.properties
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,8 @@ bisqEasy.offerbook.offerList.ExpandedList.Tooltip=Collapse Offer List
bisqEasy.offerbook.offerList.table.columns.peerProfile=Peer profile
bisqEasy.offerbook.offerList.table.columns.price=Price
bisqEasy.offerbook.offerList.table.columns.fiatAmount={0} amount
bisqEasy.offerbook.offerList.table.columns.paymentMethod=Payment
bisqEasy.offerbook.offerList.table.columns.settlementMethod=Settlement
bisqEasy.offerbook.offerList.table.filters.offerDirection.buyFrom=Buy from
bisqEasy.offerbook.offerList.table.filters.offerDirection.sellTo=Sell to

Expand Down
Loading
Loading