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

Various fixes and improvements for buyer as maker case #2052

Merged
merged 2 commits into from
Apr 15, 2024
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 @@ -48,6 +48,7 @@

import javax.annotation.Nullable;
import java.util.Optional;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;

Expand Down Expand Up @@ -120,7 +121,10 @@ public void onActivate() {
tradePhaseBox.setBisqEasyTrade(bisqEasyTrade);

bisqEasyTradeStatePin = bisqEasyTrade.tradeStateObservable().addObserver(state ->
UIThread.run(() -> applyStateInfoVBox(state)));
UIThread.run(() -> {
applyStateInfoVBox(state);
updateShouldShowSellerPriceApprovalOverlay();
}));

errorMessagePin = bisqEasyTrade.errorMessageObservable().addObserver(errorMessage -> {
if (errorMessage != null) {
Expand Down Expand Up @@ -207,26 +211,29 @@ void onInterruptTrade() {

new Popup().warning(message)
.actionButtonText(Res.get("confirmation.yes"))
.onAction(() -> {
switch (model.getTradeCloseType()) {
case REJECT:
channelService.sendSystemMessage(Res.get("bisqEasy.openTrades.systemMessage.rejected",
model.getChannel().get().getMyUserIdentity().getUserName()), model.getChannel().get());
bisqEasyTradeService.rejectTrade(trade);
break;
case CANCEL:
channelService.sendSystemMessage(Res.get("bisqEasy.openTrades.systemMessage.cancelled",
model.getChannel().get().getMyUserIdentity().getUserName()), model.getChannel().get());
bisqEasyTradeService.cancelTrade(trade);
break;
case COMPLETED:
default:
}
})
.onAction(this::doInterruptTrade)
.closeButtonText(Res.get("confirmation.no"))
.show();
}

void doInterruptTrade() {
BisqEasyTrade trade = model.getBisqEasyTrade().get();
switch (model.getTradeCloseType()) {
case REJECT:
channelService.sendSystemMessage(Res.get("bisqEasy.openTrades.systemMessage.rejected",
model.getChannel().get().getMyUserIdentity().getUserName()), model.getChannel().get());
bisqEasyTradeService.rejectTrade(trade);
break;
case CANCEL:
channelService.sendSystemMessage(Res.get("bisqEasy.openTrades.systemMessage.cancelled",
model.getChannel().get().getMyUserIdentity().getUserName()), model.getChannel().get());
bisqEasyTradeService.cancelTrade(trade);
break;
case COMPLETED:
default:
}
}

void onCloseTrade() {
new Popup().warning(Res.get("bisqEasy.openTrades.closeTrade.warning.interrupted"))
.actionButtonText(Res.get("confirmation.yes"))
Expand Down Expand Up @@ -482,6 +489,15 @@ && requiresSellerPriceAcceptance()
private boolean requiresSellerPriceAcceptance() {
PriceSpec buyerPriceSpec = model.getBisqEasyTrade().get().getOffer().getPriceSpec();
PriceSpec sellerPriceSpec = model.getBisqEasyTrade().get().getContract().getAgreedPriceSpec();
return !buyerPriceSpec.equals(sellerPriceSpec);
boolean priceSpecChanged = !buyerPriceSpec.equals(sellerPriceSpec);

Set<BisqEasyTradeState> validStatesToRejectPrice = Set.of(
BisqEasyTradeState.MAKER_SENT_TAKE_OFFER_RESPONSE__BUYER_DID_NOT_SENT_BTC_ADDRESS__BUYER_DID_NOT_RECEIVED_ACCOUNT_DATA,
BisqEasyTradeState.MAKER_SENT_TAKE_OFFER_RESPONSE__BUYER_DID_NOT_SENT_BTC_ADDRESS__BUYER_RECEIVED_ACCOUNT_DATA,
BisqEasyTradeState.MAKER_DID_NOT_SENT_TAKE_OFFER_RESPONSE__BUYER_DID_NOT_SENT_BTC_ADDRESS__BUYER_RECEIVED_ACCOUNT_DATA,
BisqEasyTradeState.MAKER_SENT_TAKE_OFFER_RESPONSE__BUYER_DID_NOT_SENT_BTC_ADDRESS__BUYER_RECEIVED_ACCOUNT_DATA_
);
boolean isInValidStateToRejectPrice = validStatesToRejectPrice.contains(model.getBisqEasyTrade().get().tradeStateObservable().get());
return priceSpecChanged && isInValidStateToRejectPrice;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public class TradeStateView extends View<VBox, TradeStateModel, TradeStateContro
private final Button cancelButton, closeTradeButton, exportButton, reportToMediatorButton, acceptSellersPriceButton,
rejectPriceButton;
private final Label cancelledInfo, errorMessage;
private VBox sellerPriceApprovalOverlay;
private Pane sellerPriceApprovalContent;
private final VBox sellerPriceApprovalOverlay;
private final Pane sellerPriceApprovalContent;
private Subscription stateInfoVBoxPin, showSellersPriceApprovalOverlayPin, sellerPriceApprovalContentPin;

public TradeStateView(TradeStateModel model,
Expand All @@ -57,10 +57,6 @@ public TradeStateView(TradeStateModel model,
cancelButton.setMinWidth(160);
cancelButton.getStyleClass().add("outlined-button");

rejectPriceButton = new Button();
rejectPriceButton.setMinWidth(160);
rejectPriceButton.setDefaultButton(true);

tradeDataHeader.getChildren().addAll(Spacer.fillHBox(), cancelButton);


Expand Down Expand Up @@ -116,9 +112,14 @@ public TradeStateView(TradeStateModel model,
VBox content = new VBox(tradeDataHeader, Layout.hLine(), isInMediationHBox, interruptedHBox, phaseAndInfoHBox);
content.getStyleClass().add("bisq-easy-container");

// Accept seller's price overlay
sellerPriceApprovalContent = new Pane();
acceptSellersPriceButton = new Button(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.button.accept"));
acceptSellersPriceButton.getStyleClass().add("outlined-button");
setUpSellerPriceApprovalOverlay();
rejectPriceButton = new Button();
rejectPriceButton.setMinWidth(160);
rejectPriceButton.setDefaultButton(true);
sellerPriceApprovalOverlay = createAndGetSellerPriceApprovalOverlay();

StackPane layeredContent = new StackPane(content, sellerPriceApprovalOverlay);
root.getChildren().add(layeredContent);
Expand All @@ -143,12 +144,10 @@ protected void onViewAttached() {
errorMessage.textProperty().bind(model.getErrorMessage());

cancelButton.textProperty().bind(model.getInterruptTradeButtonText());
cancelButton.visibleProperty().bind(model.getCancelButtonVisible());
cancelButton.managedProperty().bind(model.getCancelButtonVisible());
cancelButton.visibleProperty().bind(model.getCancelButtonVisible().and(model.getShouldShowSellerPriceApprovalOverlay().not()));
cancelButton.managedProperty().bind(model.getCancelButtonVisible().and(model.getShouldShowSellerPriceApprovalOverlay().not()));

rejectPriceButton.textProperty().bind(model.getInterruptTradeButtonText());
rejectPriceButton.visibleProperty().bind(model.getCancelButtonVisible());
rejectPriceButton.managedProperty().bind(model.getCancelButtonVisible());

stateInfoVBoxPin = EasyBind.subscribe(model.getStateInfoVBox(), stateInfoVBox -> {
if (phaseAndInfoHBox.getChildren().size() == 2) {
Expand Down Expand Up @@ -184,7 +183,7 @@ protected void onViewAttached() {
cancelButton.setOnAction(e -> controller.onInterruptTrade());
closeTradeButton.setOnAction(e -> controller.onCloseTrade());
exportButton.setOnAction(e -> controller.onExportTrade());
rejectPriceButton.setOnAction(e -> controller.onInterruptTrade());
rejectPriceButton.setOnAction(e -> controller.doInterruptTrade());
reportToMediatorButton.setOnAction(e -> controller.onReportToMediator());
acceptSellersPriceButton.setOnAction(e -> controller.onAcceptSellersPriceButton());
}
Expand Down Expand Up @@ -212,8 +211,6 @@ protected void onViewDetached() {
cancelButton.managedProperty().unbind();

rejectPriceButton.textProperty().unbind();
rejectPriceButton.visibleProperty().unbind();
rejectPriceButton.managedProperty().unbind();

stateInfoVBoxPin.unsubscribe();
showSellersPriceApprovalOverlayPin.unsubscribe();
Expand All @@ -231,26 +228,33 @@ protected void onViewDetached() {
}
}

private void setUpSellerPriceApprovalOverlay() {
sellerPriceApprovalOverlay = new VBox();
sellerPriceApprovalOverlay.setAlignment(Pos.TOP_LEFT);
sellerPriceApprovalOverlay.getStyleClass().addAll("trade-wizard-feedback-bg", "seller-price-approval-popup");
sellerPriceApprovalOverlay.visibleProperty().set(false);
sellerPriceApprovalOverlay.managedProperty().set(false);
private VBox createAndGetSellerPriceApprovalOverlay() {
VBox overlay = new VBox(10);
overlay.setAlignment(Pos.TOP_LEFT);
overlay.getStyleClass().addAll("trade-wizard-feedback-bg", "seller-price-approval-popup");
overlay.visibleProperty().set(false);
overlay.managedProperty().set(false);

Label titleLabel = new Label(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.title"));
titleLabel.getStyleClass().addAll("seller-price-approval-title", "large-text", "font-default");

Label sellerPriceApprovalTitleLabel = new Label(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.title"));
sellerPriceApprovalTitleLabel.getStyleClass().addAll("seller-price-approval-title", "large-text", "font-default");
sellerPriceApprovalContent = new Pane();
sellerPriceApprovalContent.getStyleClass().addAll("seller-price-approval-description", "normal-text", "font-default");
Label sellerPriceApprovalQuestionLabel = new Label(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.description.question"));
sellerPriceApprovalQuestionLabel.getStyleClass().addAll("seller-price-approval-description", "normal-text",

Label questionLabel = new Label(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.description.question"));
questionLabel.getStyleClass().addAll("seller-price-approval-description", "normal-text",
"font-default", "seller-price-approval-question");
HBox sellerPriceApprovalButtons = new HBox(10, acceptSellersPriceButton, rejectPriceButton);
sellerPriceApprovalButtons.setAlignment(Pos.BOTTOM_RIGHT);

sellerPriceApprovalOverlay.getChildren().addAll(sellerPriceApprovalTitleLabel, sellerPriceApprovalContent,
sellerPriceApprovalQuestionLabel, Spacer.fillVBox(), sellerPriceApprovalButtons);
StackPane.setAlignment(sellerPriceApprovalOverlay, Pos.TOP_CENTER);
StackPane.setMargin(sellerPriceApprovalOverlay, new Insets(63, 0, 0, 0));
Label disclaimerLabel = new Label(Res.get("bisqEasy.tradeState.acceptOrRejectSellersPrice.description.disclaimer"));
disclaimerLabel.getStyleClass().addAll("seller-price-approval-description", "small-text", "font-default",
"seller-price-approval-disclaimer");

HBox acceptOrRejectButtons = new HBox(10, acceptSellersPriceButton, rejectPriceButton);
acceptOrRejectButtons.setAlignment(Pos.BOTTOM_RIGHT);

overlay.getChildren().addAll(titleLabel, sellerPriceApprovalContent,
questionLabel, disclaimerLabel, Spacer.fillVBox(), acceptOrRejectButtons);
StackPane.setAlignment(overlay, Pos.TOP_CENTER);
StackPane.setMargin(overlay, new Insets(63, 0, 0, 0));
return overlay;
}
}
11 changes: 9 additions & 2 deletions apps/desktop/desktop/src/main/resources/css/bisq_easy.css
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@
.seller-price-approval-popup .seller-price-approval-content {
-fx-fill: -fx-light-text-color;
-fx-text-fill: -fx-light-text-color;
-fx-padding: 30 0 0 0;
-fx-padding: 15 0 0 0;
-fx-spacing: 10;
}

Expand All @@ -464,7 +464,14 @@
}

.seller-price-approval-popup .seller-price-approval-question {
-fx-padding: 30 0 0 0;
-fx-line-spacing: 10;
}

.seller-price-approval-popup .seller-price-approval-disclaimer {
-fx-padding: 10 0 0 0;
-fx-fill: -fx-mid-text-color;
-fx-text-fill: -fx-mid-text-color;
-fx-line-spacing: 10;
}


Expand Down
11 changes: 6 additions & 5 deletions i18n/src/main/resources/bisq_easy.properties
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ bisqEasy.price.feedback.sentence.veryGood=very good
bisqEasy.price.feedback.learnWhySection.openButton=Why?
bisqEasy.price.feedback.learnWhySection.closeButton=Back to Trade Price
bisqEasy.price.feedback.learnWhySection.title=Why should I pay a higher price to the seller?
bisqEasy.price.feedback.learnWhySection.description.intro=The reason for that is that the seller has to cover extra expenses\
bisqEasy.price.feedback.learnWhySection.description.intro=The reason for that is that the seller has to cover extra expenses \
and compensate for the seller's service specifically:
bisqEasy.price.feedback.learnWhySection.description.exposition=\
- Build up reputation which can be costly.\
Expand Down Expand Up @@ -576,10 +576,11 @@ bisqEasy.openTrades.welcome.line3=Make yourself familiar with the trade rules

bisqEasy.tradeState.requestMediation=Request mediation
bisqEasy.tradeState.reportToMediator=Report to mediator
bisqEasy.tradeState.acceptOrRejectSellersPrice.title=Attention!
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.buyersPrice=Your offer price to buy Bitcoin was: {0}.
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.sellersPrice=However, the seller is offering you this price: {0}.
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.question=Do you want to accept this new price or do you want to cancel/reject the trade?
bisqEasy.tradeState.acceptOrRejectSellersPrice.title=Attention to Price Change!
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.buyersPrice=Your offer price to buy Bitcoin was {0}.
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.sellersPrice=However, the seller is offering you this price {0}.
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.question=Do you want to accept this new price or do you want to reject/cancel* the trade?
bisqEasy.tradeState.acceptOrRejectSellersPrice.description.disclaimer=(*Note that in this specific case, cancelling the trade will NOT be considered a violation of the trading rules.)
bisqEasy.tradeState.acceptOrRejectSellersPrice.button.accept=Accept price

# Trade State: Header
Expand Down
Loading