mirror of
https://github.com/bisq-network/bisq.git
synced 2024-11-19 09:52:23 +01:00
Dispute subsystem enhancements.
Dispute result show payout suggestion and penalty. Feature allowing trader chat upload to dispute agents.
This commit is contained in:
parent
e7f1bf2d7d
commit
7e802e5e28
@ -17,6 +17,7 @@
|
||||
|
||||
package bisq.core.support.dispute;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.support.messages.ChatMessage;
|
||||
|
||||
import bisq.common.proto.ProtoUtil;
|
||||
@ -68,14 +69,30 @@ public final class DisputeResult implements NetworkPayload {
|
||||
}
|
||||
|
||||
public enum PayoutSuggestion {
|
||||
UNKNOWN,
|
||||
BUYER_GETS_TRADE_AMOUNT,
|
||||
BUYER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION,
|
||||
BUYER_GETS_TRADE_AMOUNT_MINUS_PENALTY,
|
||||
SELLER_GETS_TRADE_AMOUNT,
|
||||
SELLER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION,
|
||||
SELLER_GETS_TRADE_AMOUNT_MINUS_PENALTY,
|
||||
CUSTOM_PAYOUT
|
||||
UNKNOWN("shared.na", null),
|
||||
BUYER_GETS_TRADE_AMOUNT("disputeSummaryWindow.payout.getsTradeAmount", "shared.buyer"),
|
||||
BUYER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION("disputeSummaryWindow.payout.getsCompensation", "shared.buyer"),
|
||||
BUYER_GETS_TRADE_AMOUNT_MINUS_PENALTY("disputeSummaryWindow.payout.getsPenalty", "shared.buyer"),
|
||||
SELLER_GETS_TRADE_AMOUNT("disputeSummaryWindow.payout.getsTradeAmount", "shared.seller"),
|
||||
SELLER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION("disputeSummaryWindow.payout.getsCompensation", "shared.seller"),
|
||||
SELLER_GETS_TRADE_AMOUNT_MINUS_PENALTY("disputeSummaryWindow.payout.getsPenalty", "shared.seller"),
|
||||
CUSTOM_PAYOUT("disputeSummaryWindow.payout.custom", null);
|
||||
|
||||
private String suggestionKey;
|
||||
@Nullable private String buyerSellerKey;
|
||||
|
||||
PayoutSuggestion(String suggestionKey, @Nullable String buyerSellerKey) {
|
||||
this.suggestionKey = suggestionKey;
|
||||
this.buyerSellerKey = buyerSellerKey;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (buyerSellerKey == null) {
|
||||
return Res.get(suggestionKey);
|
||||
} else {
|
||||
return Res.get(suggestionKey, Res.get(buyerSellerKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final String tradeId;
|
||||
@ -259,6 +276,17 @@ public final class DisputeResult implements NetworkPayload {
|
||||
return new Date(closeDate);
|
||||
}
|
||||
|
||||
public String getPayoutSuggestionText() {
|
||||
if (payoutSuggestion.equals(PayoutSuggestion.BUYER_GETS_TRADE_AMOUNT_MINUS_PENALTY)
|
||||
|| payoutSuggestion.equals(PayoutSuggestion.BUYER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION)
|
||||
|| payoutSuggestion.equals(PayoutSuggestion.SELLER_GETS_TRADE_AMOUNT_MINUS_PENALTY)
|
||||
|| payoutSuggestion.equals(PayoutSuggestion.SELLER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION)) {
|
||||
return payoutSuggestion + " " + payoutAdjustmentPercent + "%";
|
||||
}
|
||||
return payoutSuggestion.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DisputeResult{" +
|
||||
|
@ -1223,14 +1223,16 @@ support.state=State
|
||||
support.chat=Chat
|
||||
support.closed=Closed
|
||||
support.open=Open
|
||||
support.moreButton=MORE...
|
||||
support.sendLogFiles=Send Log Files
|
||||
support.uploadTraderChat=Upload Trader Chat
|
||||
support.process=Process
|
||||
support.buyerOfferer=BTC buyer/Maker
|
||||
support.sellerOfferer=BTC seller/Maker
|
||||
support.buyerTaker=BTC buyer/Taker
|
||||
support.sellerTaker=BTC seller/Taker
|
||||
support.sendLogs.title=Send Log Files
|
||||
support.sendLogs.backgroundInfo=When you experience a bug, mediators and support staff will often request copies of the your log files to diagnose the issue.\n\n\ \
|
||||
support.sendLogs.backgroundInfo=When you experience a bug, mediators and support staff will often request copies of the your log files to diagnose the issue.\n\n\
|
||||
Upon pressing 'Send', your log files will be compressed and transmitted directly to the mediator.
|
||||
support.sendLogs.step1=Create Zip Archive of Log Files
|
||||
support.sendLogs.step2=Connection Request to Mediator
|
||||
@ -2726,11 +2728,12 @@ disputeSummaryWindow.close.msg=Ticket closed on {0}\n\
|
||||
Summary:\n\
|
||||
Trade ID: {3}\n\
|
||||
Currency: {4}\n\
|
||||
Trade amount: {5}\n\
|
||||
Payout amount for BTC buyer: {6}\n\
|
||||
Payout amount for BTC seller: {7}\n\n\
|
||||
Reason for dispute: {8}\n\n\
|
||||
Summary notes:\n{9}\n
|
||||
Reason for dispute: {5}\n\
|
||||
Payout suggestion: {6}\n\
|
||||
Trade amount: {7}\n\
|
||||
Payout amount for BTC buyer: {8}\n\
|
||||
Payout amount for BTC seller: {9}\n\n\
|
||||
Summary notes:\n{10}\n
|
||||
|
||||
# Do no change any line break or order of tokens as the structure is used for signature verification
|
||||
disputeSummaryWindow.close.msgWithSig={0}{1}{2}{3}
|
||||
|
@ -334,13 +334,20 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
}
|
||||
|
||||
private void addTradeAmountPayoutControls() {
|
||||
buyerGetsTradeAmountRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsTradeAmount", Res.get("shared.buyer")));
|
||||
buyerGetsCompensationRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsCompensation", Res.get("shared.buyer")));
|
||||
buyerGetsTradeAmountMinusPenaltyRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsPenalty", Res.get("shared.buyer")));
|
||||
sellerGetsTradeAmountRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsTradeAmount", Res.get("shared.seller")));
|
||||
sellerGetsCompensationRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsCompensation", Res.get("shared.seller")));
|
||||
sellerGetsTradeAmountMinusPenaltyRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.getsPenalty", Res.get("shared.seller")));
|
||||
customRadioButton = new AutoTooltipRadioButton(Res.get("disputeSummaryWindow.payout.custom"));
|
||||
buyerGetsTradeAmountRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.BUYER_GETS_TRADE_AMOUNT.toString());
|
||||
buyerGetsCompensationRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.BUYER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION.toString());
|
||||
buyerGetsTradeAmountMinusPenaltyRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.BUYER_GETS_TRADE_AMOUNT_MINUS_PENALTY.toString());
|
||||
sellerGetsTradeAmountRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.SELLER_GETS_TRADE_AMOUNT.toString());
|
||||
sellerGetsCompensationRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.SELLER_GETS_TRADE_AMOUNT_PLUS_COMPENSATION.toString());
|
||||
sellerGetsTradeAmountMinusPenaltyRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.SELLER_GETS_TRADE_AMOUNT_MINUS_PENALTY.toString());
|
||||
customRadioButton = new AutoTooltipRadioButton(
|
||||
DisputeResult.PayoutSuggestion.CUSTOM_PAYOUT.toString());
|
||||
|
||||
VBox radioButtonPane = new VBox();
|
||||
radioButtonPane.setSpacing(10);
|
||||
@ -877,10 +884,11 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
|
||||
agentNodeAddress,
|
||||
dispute.getShortTradeId(),
|
||||
currencyCode,
|
||||
Res.get("disputeSummaryWindow.reason." + reason.name()),
|
||||
disputeResult.getPayoutSuggestionText(),
|
||||
amount,
|
||||
formatter.formatCoinWithCode(disputeResult.getBuyerPayoutAmount()),
|
||||
formatter.formatCoinWithCode(disputeResult.getSellerPayoutAmount()),
|
||||
Res.get("disputeSummaryWindow.reason." + reason.name()),
|
||||
disputeResult.summaryNotesProperty().get()
|
||||
);
|
||||
|
||||
|
@ -45,6 +45,7 @@ import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.stage.FileChooser;
|
||||
|
||||
import javafx.scene.Node;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListCell;
|
||||
@ -112,7 +113,7 @@ public class ChatView extends AnchorPane {
|
||||
|
||||
// Options
|
||||
@Getter
|
||||
Button extraButton;
|
||||
Node extraButton;
|
||||
@Getter
|
||||
private ReadOnlyDoubleProperty widthProperty;
|
||||
@Setter
|
||||
@ -169,7 +170,7 @@ public class ChatView extends AnchorPane {
|
||||
}
|
||||
|
||||
public void display(SupportSession supportSession,
|
||||
@Nullable Button extraButton,
|
||||
@Nullable Node extraButton,
|
||||
ReadOnlyDoubleProperty widthProperty) {
|
||||
optionalSupportSession = Optional.of(supportSession);
|
||||
removeListenersOnSessionChange();
|
||||
@ -233,7 +234,6 @@ public class ChatView extends AnchorPane {
|
||||
buttonBox.getChildren().addAll(sendButton, sendMsgBusyAnimation, sendMsgInfoLabel);
|
||||
|
||||
if (extraButton != null) {
|
||||
extraButton.setDefaultButton(true);
|
||||
Pane spacer = new Pane();
|
||||
HBox.setHgrow(spacer, Priority.ALWAYS);
|
||||
buttonBox.getChildren().addAll(spacer, extraButton);
|
||||
@ -571,6 +571,26 @@ public class ChatView extends AnchorPane {
|
||||
}
|
||||
}
|
||||
|
||||
public void onAttachText(String textAttachment, String name) {
|
||||
if (!allowAttachments)
|
||||
return;
|
||||
try {
|
||||
byte[] filesAsBytes = textAttachment.getBytes("UTF8");
|
||||
int size = filesAsBytes.length;
|
||||
int maxMsgSize = Connection.getPermittedMessageSize();
|
||||
int maxSizeInKB = maxMsgSize / 1024;
|
||||
if (size > maxMsgSize) {
|
||||
new Popup().warning(Res.get("support.attachmentTooLarge", (size / 1024), maxSizeInKB)).show();
|
||||
} else {
|
||||
tempAttachments.add(new Attachment(name, filesAsBytes));
|
||||
inputTextArea.setText(inputTextArea.getText() + "\n[" + Res.get("support.attachment") + " " + name + "]");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void onOpenAttachment(Attachment attachment) {
|
||||
if (!allowAttachments)
|
||||
return;
|
||||
|
@ -21,12 +21,14 @@ import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.main.MainView;
|
||||
import bisq.desktop.main.shared.ChatView;
|
||||
import bisq.desktop.util.CssTheme;
|
||||
import bisq.desktop.util.DisplayUtils;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.support.dispute.Dispute;
|
||||
import bisq.core.support.dispute.DisputeList;
|
||||
import bisq.core.support.dispute.DisputeManager;
|
||||
import bisq.core.support.dispute.DisputeSession;
|
||||
import bisq.core.support.messages.ChatMessage;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.coin.CoinFormatter;
|
||||
|
||||
@ -39,6 +41,8 @@ import javafx.stage.Window;
|
||||
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.MenuButton;
|
||||
import javafx.scene.control.MenuItem;
|
||||
import javafx.scene.input.KeyCode;
|
||||
import javafx.scene.input.KeyEvent;
|
||||
import javafx.scene.layout.AnchorPane;
|
||||
@ -46,6 +50,9 @@ import javafx.scene.layout.StackPane;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class DisputeChatPopup {
|
||||
@ -106,12 +113,19 @@ public class DisputeChatPopup {
|
||||
} else {
|
||||
if (disputeManager.isAgent(selectedDispute)) {
|
||||
Button closeDisputeButton = new AutoTooltipButton(Res.get("support.closeTicket"));
|
||||
closeDisputeButton.setDefaultButton(true);
|
||||
closeDisputeButton.setOnAction(e -> chatCallback.onCloseDisputeFromChatWindow(selectedDispute));
|
||||
chatView.display(concreteDisputeSession, closeDisputeButton, pane.widthProperty());
|
||||
} else {
|
||||
Button sendLogsButton = new AutoTooltipButton(Res.get("support.sendLogFiles"));
|
||||
sendLogsButton.setOnAction(e -> chatCallback.onSendLogsFromChatWindow(selectedDispute));
|
||||
chatView.display(concreteDisputeSession, sendLogsButton, pane.widthProperty());
|
||||
MenuButton menuButton = new MenuButton(Res.get("support.moreButton"));
|
||||
MenuItem menuItem1 = new MenuItem(Res.get("support.uploadTraderChat"));
|
||||
MenuItem menuItem2 = new MenuItem(Res.get("support.sendLogFiles"));
|
||||
menuItem1.setOnAction(e -> doTextAttachment(chatView));
|
||||
menuItem2.setOnAction(e -> chatCallback.onSendLogsFromChatWindow(selectedDispute));
|
||||
menuButton.getItems().addAll(menuItem1, menuItem2);
|
||||
menuButton.getStyleClass().add("jfx-button");
|
||||
menuButton.setStyle("-fx-padding: 0 10 0 10;");
|
||||
chatView.display(concreteDisputeSession, menuButton, pane.widthProperty());
|
||||
}
|
||||
}
|
||||
chatView.activate();
|
||||
@ -163,4 +177,23 @@ public class DisputeChatPopup {
|
||||
// and after a short moment in the correct position
|
||||
UserThread.execute(() -> chatPopupStage.setOpacity(1));
|
||||
}
|
||||
|
||||
private void doTextAttachment(ChatView chatView) {
|
||||
disputeManager.findTrade(selectedDispute).ifPresent(t -> {
|
||||
List<ChatMessage> chatMessages = t.getChatMessages();
|
||||
if (chatMessages.size() > 0) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
chatMessages.forEach(i -> {
|
||||
boolean isMyMsg = i.isSenderIsTrader();
|
||||
String metaData = DisplayUtils.formatDateTime(new Date(i.getDate()));
|
||||
if (!i.isSystemMessage())
|
||||
metaData = (isMyMsg ? "Sent " : "Received ") + metaData
|
||||
+ (isMyMsg ? "" : " from Trader");
|
||||
stringBuilder.append(metaData).append("\n").append(i.getMessage()).append("\n\n");
|
||||
});
|
||||
String fileName = selectedDispute.getShortTradeId() + "_" + selectedDispute.getRoleStringForLogFile() + "_TraderChat.txt";
|
||||
chatView.onAttachText(stringBuilder.toString(), fileName);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user