From 4bef95172c5c34f3f1541319ae73f6229862a563 Mon Sep 17 00:00:00 2001 From: napoly <napolytan@protonmail.com> Date: Fri, 17 Mar 2023 18:43:33 +0100 Subject: [PATCH] Update Signed Offers view in legacy UI --- .github/workflows/build.yml | 8 +- .../resources/i18n/displayStrings.properties | 1 + .../signedoffer/SignedOfferListItem.java | 48 ++ .../signedoffer}/SignedOfferView.fxml | 6 +- .../offer/signedoffer/SignedOfferView.java | 358 ++++++++++++++ .../signedoffer/SignedOffersDataModel.java | 70 +++ .../signedoffer/SignedOffersViewModel.java | 39 ++ .../desktop/main/support/SupportView.java | 2 +- .../dispute/agent/SignedOfferView.java | 438 ------------------ 9 files changed, 525 insertions(+), 445 deletions(-) create mode 100644 desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferListItem.java rename desktop/src/main/java/haveno/desktop/main/{support/dispute/agent => offer/signedoffer}/SignedOfferView.fxml (87%) create mode 100644 desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.java create mode 100644 desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersDataModel.java create mode 100644 desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersViewModel.java delete mode 100644 desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 68d4af83da..bf12e778f8 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -14,11 +14,11 @@ jobs: fail-fast: false runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: lfs: true - name: Set up JDK 11 - uses: actions/setup-java@v2 + uses: actions/setup-java@v3 with: java-version: '11' distribution: 'adopt' @@ -26,11 +26,11 @@ jobs: - name: Build with Gradle run: ./gradlew build --stacktrace --scan - name: cache nodes dependencies - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 with: name: cached-localnet path: .localnet - - uses: actions/upload-artifact@v2 + - uses: actions/upload-artifact@v3 if: failure() with: name: gradlew-report diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties index 7f3830dd91..e970949a5f 100644 --- a/core/src/main/resources/i18n/displayStrings.properties +++ b/core/src/main/resources/i18n/displayStrings.properties @@ -90,6 +90,7 @@ shared.usage=Usage shared.state=Status shared.tradeId=Trade ID shared.offerId=Offer ID +shared.traderId=Trader ID shared.bankName=Bank name shared.acceptedBanks=Accepted banks shared.amountMinMax=Amount (min - max) diff --git a/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferListItem.java b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferListItem.java new file mode 100644 index 0000000000..7a1e267794 --- /dev/null +++ b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferListItem.java @@ -0,0 +1,48 @@ +/* + * This file is part of Haveno. + * + * Haveno is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Haveno is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Haveno. If not, see <http://www.gnu.org/licenses/>. + */ + +package haveno.desktop.main.offer.signedoffer; + +import org.apache.commons.lang3.StringUtils; + +import lombok.Getter; + +import haveno.core.offer.SignedOffer; +import haveno.desktop.util.filtering.FilterableListItem; + +class SignedOfferListItem implements FilterableListItem { + @Getter + private final SignedOffer signedOffer; + + SignedOfferListItem(SignedOffer signedOffer) { + this.signedOffer = signedOffer; + } + + @Override + public boolean match(String filterString) { + if (filterString.isEmpty()) { + return true; + } + if (StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getTraderId()), filterString)) { + return true; + } + if (StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getOfferId()), filterString)) { + return true; + } + return StringUtils.containsIgnoreCase(String.valueOf(signedOffer.getReserveTxKeyImages()), filterString); + } +} diff --git a/desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.fxml b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.fxml similarity index 87% rename from desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.fxml rename to desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.fxml index 38f839c51e..a12a97990b 100644 --- a/desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.fxml +++ b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.fxml @@ -17,17 +17,19 @@ ~ along with Haveno. If not, see <http://www.gnu.org/licenses/>. --> -<?import javafx.geometry.Insets?> <?import javafx.scene.control.Label?> <?import javafx.scene.control.TableView?> <?import javafx.scene.layout.HBox?> <?import javafx.scene.layout.Region?> <?import javafx.scene.layout.VBox?> -<VBox fx:id="root" fx:controller="haveno.desktop.main.support.dispute.agent.SignedOfferView" +<?import javafx.geometry.Insets?> +<?import haveno.desktop.components.list.FilterBox?> +<VBox fx:id="root" fx:controller="haveno.desktop.main.offer.signedoffer.SignedOfferView" spacing="10" xmlns:fx="http://javafx.com/fxml"> <padding> <Insets bottom="15.0" left="15.0" right="15.0" top="15.0"/> </padding> + <FilterBox fx:id="filterBox" /> <TableView fx:id="tableView" VBox.vgrow="ALWAYS" /> <HBox spacing="10"> <Label fx:id="numItems"/> diff --git a/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.java b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.java new file mode 100644 index 0000000000..dfbde8df65 --- /dev/null +++ b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOfferView.java @@ -0,0 +1,358 @@ +/* + * This file is part of Haveno. + * + * Haveno is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Haveno is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Haveno. If not, see <http://www.gnu.org/licenses/>. + */ + +package haveno.desktop.main.offer.signedoffer; + +import javax.inject.Inject; + +import javafx.fxml.FXML; + +import javafx.scene.control.ContextMenu; +import javafx.scene.control.Label; +import javafx.scene.control.MenuItem; +import javafx.scene.control.TableCell; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableRow; +import javafx.scene.control.TableView; +import javafx.scene.control.Tooltip; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Priority; +import javafx.scene.layout.Region; +import javafx.scene.layout.VBox; + +import javafx.geometry.Insets; + +import javafx.beans.property.ReadOnlyObjectWrapper; + +import javafx.collections.transformation.FilteredList; +import javafx.collections.transformation.SortedList; + +import javafx.util.Callback; +import javafx.util.Duration; + +import java.util.Comparator; +import java.util.Date; + + + +import haveno.common.util.Utilities; +import haveno.core.locale.Res; +import haveno.core.offer.SignedOffer; +import haveno.core.trade.HavenoUtils; +import haveno.core.xmr.wallet.XmrWalletService; +import haveno.desktop.common.view.ActivatableViewAndModel; +import haveno.desktop.common.view.FxmlView; +import haveno.desktop.components.AutoTooltipLabel; +import haveno.desktop.components.AutoTooltipTableColumn; +import haveno.desktop.components.HyperlinkWithIcon; +import haveno.desktop.components.InputTextField; +import haveno.desktop.components.list.FilterBox; +import haveno.desktop.main.offer.OfferViewUtil; +import haveno.desktop.main.overlays.popups.Popup; +import haveno.desktop.util.DisplayUtils; +import haveno.desktop.util.GUIUtil; + +@FxmlView +public class SignedOfferView extends ActivatableViewAndModel<VBox, SignedOffersViewModel> { + + @FXML + FilterBox filterBox; + @FXML + protected TableView<SignedOfferListItem> tableView; + @FXML + TableColumn<SignedOfferListItem, SignedOfferListItem> dateColumn; + @FXML + TableColumn<SignedOfferListItem, SignedOfferListItem> traderIdColumn; + @FXML + TableColumn<SignedOfferListItem, SignedOfferListItem> offerIdColumn; + @FXML + TableColumn<SignedOfferListItem, SignedOfferListItem> reserveTxKeyImages; + @FXML + TableColumn<SignedOfferListItem, SignedOfferListItem> makerPenaltyFeeColumn; + @FXML + InputTextField filterTextField; + @FXML + Label numItems; + @FXML + Region footerSpacer; + + private SignedOfferListItem selectedSignedOffer; + + private final XmrWalletService xmrWalletService; + + private ContextMenu contextMenu; + + @Inject + public SignedOfferView(SignedOffersViewModel model, XmrWalletService xmrWalletService) { + super(model); + this.xmrWalletService = xmrWalletService; + } + + /////////////////////////////////////////////////////////////////////////////////////////// + // Life cycle + /////////////////////////////////////////////////////////////////////////////////////////// + + @Override + public void initialize() { + Label label = new AutoTooltipLabel(Res.get("support.filter")); + HBox.setMargin(label, new Insets(5, 0, 0, 0)); + HBox.setHgrow(label, Priority.NEVER); + + filterTextField = new InputTextField(); + Tooltip tooltip = new Tooltip(); + tooltip.setShowDelay(Duration.millis(100)); + tooltip.setShowDuration(Duration.seconds(10)); + filterTextField.setTooltip(tooltip); + HBox.setHgrow(filterTextField, Priority.NEVER); + + filterTextField.setText("open"); + + setupTable(); + } + @Override + protected void activate() { + FilteredList<SignedOfferListItem> filteredList = new FilteredList<>(model.getList()); + SortedList<SignedOfferListItem> sortedList = new SortedList<>(filteredList); + sortedList.comparatorProperty().bind(tableView.comparatorProperty()); + tableView.setItems(sortedList); + filterBox.initialize(filteredList, tableView); + filterBox.activate(); + + contextMenu = new ContextMenu(); + MenuItem makerPenalization = new MenuItem( + Res.get("support.contextmenu.penalize.msg", Res.get("shared.maker").toLowerCase()) + ); + MenuItem copyToClipboard = new MenuItem(Res.get("shared.copyToClipboard")); + contextMenu.getItems().addAll(makerPenalization, copyToClipboard); + + tableView.setRowFactory(tv -> { + TableRow<SignedOfferListItem> row = new TableRow<>(); + row.setOnContextMenuRequested(event -> contextMenu.show(row, event.getScreenX(), event.getScreenY())); + return row; + }); + + copyToClipboard.setOnAction(event -> { + selectedSignedOffer = tableView.getSelectionModel().getSelectedItem(); + Utilities.copyToClipboard(selectedSignedOffer.getSignedOffer().toJson()); + }); + + makerPenalization.setOnAction(event -> { + selectedSignedOffer = tableView.getSelectionModel().getSelectedItem(); + if(selectedSignedOffer != null) { + SignedOffer signedOffer = selectedSignedOffer.getSignedOffer(); + new Popup().warning(Res.get("support.prompt.signedOffer.penalty.msg", + signedOffer.getOfferId(), + HavenoUtils.formatXmr(signedOffer.getPenaltyAmount(), true), + HavenoUtils.formatXmr(signedOffer.getReserveTxMinerFee(), true), + signedOffer.getReserveTxHash(), + signedOffer.getReserveTxKeyImages()) + ).onAction(() -> OfferViewUtil.submitTransactionHex(xmrWalletService, tableView, + signedOffer.getReserveTxHex())).show(); + } else { + new Popup().error(Res.get("support.prompt.signedOffer.error.msg")).show(); + } + }); + + GUIUtil.requestFocus(tableView); + } + + @Override + protected void deactivate() { + filterBox.deactivate(); + } + + + /////////////////////////////////////////////////////////////////////////////////////////// + // SignedOfferView + /////////////////////////////////////////////////////////////////////////////////////////// + + protected void setupTable() { + tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); + Label placeholder = new AutoTooltipLabel(Res.get("support.noTickets")); + placeholder.setWrapText(true); + tableView.setPlaceholder(placeholder); + tableView.getSelectionModel().clearSelection(); + + dateColumn = getDateColumn(); + tableView.getColumns().add(dateColumn); + + traderIdColumn = getTraderIdColumn(); + tableView.getColumns().add(traderIdColumn); + + offerIdColumn = getOfferIdColumn(); + tableView.getColumns().add(offerIdColumn); + + makerPenaltyFeeColumn = getMakerPenaltyFeeColumn(); + tableView.getColumns().add(makerPenaltyFeeColumn); + + reserveTxKeyImages = getReserveTxKeyImagesColumn(); + tableView.getColumns().add(reserveTxKeyImages); + + traderIdColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getTraderId())); + offerIdColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getOfferId())); + dateColumn.setComparator(Comparator.comparing(o -> o.getSignedOffer().getTimeStamp())); + + dateColumn.setSortType(TableColumn.SortType.DESCENDING); + tableView.getSortOrder().add(dateColumn); + } + + private TableColumn<SignedOfferListItem, SignedOfferListItem> getDateColumn() { + TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.date")) { + { + setMinWidth(180); + } + }; + column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); + column.setCellFactory( + new Callback<>() { + @Override + public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) { + return new TableCell<>() { + @Override + public void updateItem(final SignedOfferListItem item, boolean empty) { + super.updateItem(item, empty); + if (item != null && !empty) + setText(DisplayUtils.formatDateTime(new Date(item.getSignedOffer().getTimeStamp()))); + else + setText(""); + } + }; + } + }); + return column; + } + + private TableColumn<SignedOfferListItem, SignedOfferListItem> getTraderIdColumn() { + TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.traderId")) { + { + setMinWidth(110); + } + }; + column.setCellValueFactory(signedOffer -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); + column.setCellFactory( + new Callback<>() { + @Override + public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) { + return new TableCell<>() { + private HyperlinkWithIcon field; + + @Override + public void updateItem(final SignedOfferListItem item, boolean empty) { + super.updateItem(item, empty); + + if (item != null && !empty) { + setText(String.valueOf(item.getSignedOffer().getTraderId())); + setGraphic(field); + } else { + setGraphic(null); + setText(""); + if (field != null) + field.setOnAction(null); + } + } + }; + } + }); + return column; + } + + private TableColumn<SignedOfferListItem, SignedOfferListItem> getOfferIdColumn() { + TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) { + { + setMinWidth(110); + } + }; + column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); + column.setCellFactory( + new Callback<>() { + @Override + public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) { + return new TableCell<>() { + private HyperlinkWithIcon field; + + @Override + public void updateItem(final SignedOfferListItem item, boolean empty) { + super.updateItem(item, empty); + + if (item != null && !empty) { + setText(String.valueOf(item.getSignedOffer().getOfferId())); + setGraphic(field); + } else { + setGraphic(null); + setText(""); + if (field != null) + field.setOnAction(null); + } + } + }; + } + }); + return column; + } + + private TableColumn<SignedOfferListItem, SignedOfferListItem> getMakerPenaltyFeeColumn() { + TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("support.maker.penalty.fee")) { + { + setMinWidth(160); + } + }; + column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); + column.setCellFactory( + new Callback<>() { + @Override + public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) { + return new TableCell<>() { + @Override + public void updateItem(final SignedOfferListItem item, boolean empty) { + super.updateItem(item, empty); + if (item != null && !empty) + setText(HavenoUtils.formatXmr(item.getSignedOffer().getPenaltyAmount(), true)); + else + setText(""); + } + }; + } + }); + return column; + } + + private TableColumn<SignedOfferListItem, SignedOfferListItem> getReserveTxKeyImagesColumn() { + TableColumn<SignedOfferListItem, SignedOfferListItem> column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) { + { + setMinWidth(160); + } + }; + column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); + column.setCellFactory( + new Callback<>() { + @Override + public TableCell<SignedOfferListItem, SignedOfferListItem> call(TableColumn<SignedOfferListItem, SignedOfferListItem> column) { + return new TableCell<>() { + @Override + public void updateItem(final SignedOfferListItem item, boolean empty) { + super.updateItem(item, empty); + if (item != null && !empty) + setText(item.getSignedOffer().getReserveTxKeyImages().toString()); + else + setText(""); + } + }; + } + }); + return column; + } +} diff --git a/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersDataModel.java b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersDataModel.java new file mode 100644 index 0000000000..bdd66388f1 --- /dev/null +++ b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersDataModel.java @@ -0,0 +1,70 @@ +/* + * This file is part of Haveno. + * + * Haveno is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Haveno is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Haveno. If not, see <http://www.gnu.org/licenses/>. + */ + +package haveno.desktop.main.offer.signedoffer; + +import com.google.inject.Inject; + +import javafx.collections.FXCollections; +import javafx.collections.ListChangeListener; +import javafx.collections.ObservableList; + +import java.util.stream.Collectors; + + + +import haveno.core.offer.OpenOfferManager; +import haveno.core.offer.SignedOffer; +import haveno.desktop.common.model.ActivatableDataModel; +import java.sql.Date; + +class SignedOffersDataModel extends ActivatableDataModel { + private final OpenOfferManager openOfferManager; + private final ObservableList<SignedOfferListItem> list = FXCollections.observableArrayList(); + private final ListChangeListener<SignedOffer> tradesListChangeListener; + + @Inject + public SignedOffersDataModel(OpenOfferManager openOfferManager) { + this.openOfferManager = openOfferManager; + + tradesListChangeListener = change -> applyList(); + } + + @Override + protected void activate() { + openOfferManager.getObservableSignedOffersList().addListener(tradesListChangeListener); + applyList(); + } + + @Override + protected void deactivate() { + openOfferManager.getObservableSignedOffersList().removeListener(tradesListChangeListener); + } + + public ObservableList<SignedOfferListItem> getList() { + return list; + } + + private void applyList() { + list.clear(); + + list.addAll(openOfferManager.getObservableSignedOffersList().stream().map(SignedOfferListItem::new).collect(Collectors.toList())); + + // we sort by date, the earliest first + list.sort((o1, o2) -> new Date(o2.getSignedOffer().getTimeStamp()).compareTo(new Date(o1.getSignedOffer().getTimeStamp()))); + } +} diff --git a/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersViewModel.java b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersViewModel.java new file mode 100644 index 0000000000..511f6ca4bb --- /dev/null +++ b/desktop/src/main/java/haveno/desktop/main/offer/signedoffer/SignedOffersViewModel.java @@ -0,0 +1,39 @@ +/* + * This file is part of Haveno. + * + * Haveno is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Haveno is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Haveno. If not, see <http://www.gnu.org/licenses/>. + */ + +package haveno.desktop.main.offer.signedoffer; + +import com.google.inject.Inject; + +import javafx.collections.ObservableList; + + + +import haveno.desktop.common.model.ActivatableWithDataModel; +import haveno.desktop.common.model.ViewModel; + +class SignedOffersViewModel extends ActivatableWithDataModel<SignedOffersDataModel> implements ViewModel { + + @Inject + public SignedOffersViewModel(SignedOffersDataModel model) { + super(model); + } + + public ObservableList<SignedOfferListItem> getList() { + return dataModel.getList(); + } +} diff --git a/desktop/src/main/java/haveno/desktop/main/support/SupportView.java b/desktop/src/main/java/haveno/desktop/main/support/SupportView.java index 8fa04ba674..3dd7864de0 100644 --- a/desktop/src/main/java/haveno/desktop/main/support/SupportView.java +++ b/desktop/src/main/java/haveno/desktop/main/support/SupportView.java @@ -38,7 +38,7 @@ import haveno.desktop.common.view.View; import haveno.desktop.common.view.ViewLoader; import haveno.desktop.main.MainView; import haveno.desktop.main.overlays.popups.Popup; -import haveno.desktop.main.support.dispute.agent.SignedOfferView; +import haveno.desktop.main.offer.signedoffer.SignedOfferView; import haveno.desktop.main.support.dispute.agent.arbitration.ArbitratorView; import haveno.desktop.main.support.dispute.agent.mediation.MediatorView; import haveno.desktop.main.support.dispute.agent.refund.RefundAgentView; diff --git a/desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.java b/desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.java deleted file mode 100644 index 4e5ad2be5d..0000000000 --- a/desktop/src/main/java/haveno/desktop/main/support/dispute/agent/SignedOfferView.java +++ /dev/null @@ -1,438 +0,0 @@ -/* - * This file is part of Haveno. - * - * Haveno is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Haveno is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Haveno. If not, see <http://www.gnu.org/licenses/>. - */ - -package haveno.desktop.main.support.dispute.agent; - -import haveno.common.UserThread; -import haveno.common.util.Utilities; -import haveno.core.locale.Res; -import haveno.core.offer.OpenOfferManager; -import haveno.core.offer.SignedOffer; -import haveno.core.trade.HavenoUtils; -import haveno.core.xmr.wallet.XmrWalletService; -import haveno.desktop.common.view.ActivatableView; -import haveno.desktop.common.view.FxmlView; -import haveno.desktop.components.AutoTooltipLabel; -import haveno.desktop.components.AutoTooltipTableColumn; -import haveno.desktop.components.HyperlinkWithIcon; -import haveno.desktop.components.InputTextField; -import haveno.desktop.main.offer.OfferViewUtil; -import haveno.desktop.main.overlays.popups.Popup; -import haveno.desktop.util.DisplayUtils; -import haveno.desktop.util.GUIUtil; -import javafx.beans.property.ReadOnlyObjectWrapper; -import javafx.collections.ListChangeListener; -import javafx.collections.transformation.SortedList; -import javafx.fxml.FXML; -import javafx.geometry.Insets; -import javafx.scene.control.ContextMenu; -import javafx.scene.control.Label; -import javafx.scene.control.MenuItem; -import javafx.scene.control.TableCell; -import javafx.scene.control.TableColumn; -import javafx.scene.control.TableRow; -import javafx.scene.control.TableView; -import javafx.scene.control.Tooltip; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.Region; -import javafx.scene.layout.VBox; -import javafx.util.Callback; -import javafx.util.Duration; - -import javax.inject.Inject; -import java.util.Comparator; -import java.util.Date; - -@FxmlView -public class SignedOfferView extends ActivatableView<VBox, Void> { - - private final OpenOfferManager openOfferManager; - - @FXML - protected TableView<SignedOffer> tableView; - @FXML - TableColumn<SignedOffer, SignedOffer> dateColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> offerIdColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> reserveTxHashColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> reserveTxHexColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> reserveTxKeyImages; - @FXML - TableColumn<SignedOffer, SignedOffer> arbitratorSignatureColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> reserveTxMinerFeeColumn; - @FXML - TableColumn<SignedOffer, SignedOffer> makerPenaltyFeeColumn; - @FXML - InputTextField filterTextField; - @FXML - Label numItems; - @FXML - Region footerSpacer; - - private SignedOffer selectedSignedOffer; - - private XmrWalletService xmrWalletService; - - private ContextMenu contextMenu; - - private final ListChangeListener<SignedOffer> signedOfferListChangeListener; - - @Inject - public SignedOfferView(OpenOfferManager openOfferManager, XmrWalletService xmrWalletService) { - this.openOfferManager = openOfferManager; - this.xmrWalletService = xmrWalletService; - - signedOfferListChangeListener = change -> applyList(); - } - - private void applyList() { - UserThread.execute(() -> { - SortedList<SignedOffer> sortedList = new SortedList<>(openOfferManager.getObservableSignedOffersList()); - sortedList.comparatorProperty().bind(tableView.comparatorProperty()); - tableView.setItems(sortedList); - numItems.setText(Res.get("shared.numItemsLabel", sortedList.size())); - }); - } - - /////////////////////////////////////////////////////////////////////////////////////////// - // Life cycle - /////////////////////////////////////////////////////////////////////////////////////////// - - @Override - public void initialize() { - Label label = new AutoTooltipLabel(Res.get("support.filter")); - HBox.setMargin(label, new Insets(5, 0, 0, 0)); - HBox.setHgrow(label, Priority.NEVER); - - filterTextField = new InputTextField(); - Tooltip tooltip = new Tooltip(); - tooltip.setShowDelay(Duration.millis(100)); - tooltip.setShowDuration(Duration.seconds(10)); - filterTextField.setTooltip(tooltip); - HBox.setHgrow(filterTextField, Priority.NEVER); - - filterTextField.setText("open"); - - setupTable(); - } - @Override - protected void activate() { - super.activate(); - - applyList(); - openOfferManager.getObservableSignedOffersList().addListener(signedOfferListChangeListener); - contextMenu = new ContextMenu(); - MenuItem item1 = new MenuItem(Res.get("support.contextmenu.penalize.msg", - Res.get("shared.maker"))); - contextMenu.getItems().addAll(item1); - - tableView.setRowFactory(tv -> { - TableRow<SignedOffer> row = new TableRow<>(); - row.setOnContextMenuRequested(event -> { - contextMenu.show(row, event.getScreenX(), event.getScreenY()); - }); - return row; - }); - - item1.setOnAction(event -> { - selectedSignedOffer = tableView.getSelectionModel().getSelectedItem(); - if(selectedSignedOffer != null) { - new Popup().warning(Res.get("support.prompt.signedOffer.penalty.msg", - selectedSignedOffer.getOfferId(), - HavenoUtils.formatXmr(selectedSignedOffer.getPenaltyAmount(), true), - HavenoUtils.formatXmr(selectedSignedOffer.getReserveTxMinerFee(), true), - selectedSignedOffer.getReserveTxHash(), - selectedSignedOffer.getReserveTxKeyImages()) - ).onAction(() -> OfferViewUtil.submitTransactionHex(xmrWalletService, tableView, - selectedSignedOffer.getReserveTxHex())).show(); - } else { - new Popup().error(Res.get("support.prompt.signedOffer.error.msg")).show(); - } - }); - - GUIUtil.requestFocus(tableView); - } - - @Override - protected void deactivate() { - super.deactivate(); - } - - - /////////////////////////////////////////////////////////////////////////////////////////// - // SignedOfferView - /////////////////////////////////////////////////////////////////////////////////////////// - - protected void setupTable() { - tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); - Label placeholder = new AutoTooltipLabel(Res.get("support.noTickets")); - placeholder.setWrapText(true); - tableView.setPlaceholder(placeholder); - tableView.getSelectionModel().clearSelection(); - - dateColumn = getDateColumn(); - tableView.getColumns().add(dateColumn); - - offerIdColumn = getOfferIdColumn(); - tableView.getColumns().add(offerIdColumn); - - reserveTxHashColumn = getReserveTxHashColumn(); - tableView.getColumns().add(reserveTxHashColumn); - - reserveTxHexColumn = getReserveTxHexColumn(); - tableView.getColumns().add(reserveTxHexColumn); - - reserveTxKeyImages = getReserveTxKeyImagesColumn(); - tableView.getColumns().add(reserveTxKeyImages); - - arbitratorSignatureColumn = getArbitratorSignatureColumn(); - tableView.getColumns().add(arbitratorSignatureColumn); - - makerPenaltyFeeColumn = getMakerPenaltyFeeColumn(); - tableView.getColumns().add(makerPenaltyFeeColumn); - - reserveTxMinerFeeColumn = getReserveTxMinerFeeColumn(); - tableView.getColumns().add(reserveTxMinerFeeColumn); - - offerIdColumn.setComparator(Comparator.comparing(SignedOffer::getOfferId)); - dateColumn.setComparator(Comparator.comparing(SignedOffer::getTimeStamp)); - - dateColumn.setSortType(TableColumn.SortType.DESCENDING); - tableView.getSortOrder().add(dateColumn); - } - - private TableColumn<SignedOffer, SignedOffer> getDateColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("shared.date")) { - { - setMinWidth(180); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(DisplayUtils.formatDateTime(new Date(item.getTimeStamp()))); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getOfferIdColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) { - { - setMinWidth(110); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - private HyperlinkWithIcon field; - - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - - if (item != null && !empty) { - setText(item.getOfferId()); - setGraphic(field); - } else { - setGraphic(null); - setText(""); - if (field != null) - field.setOnAction(null); - } - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getReserveTxHashColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txHash")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(item.getReserveTxHash()); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getReserveTxHexColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txHex")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(item.getReserveTxHex()); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getReserveTxKeyImagesColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(item.getReserveTxKeyImages().toString()); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getArbitratorSignatureColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.signature")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(Utilities.bytesAsHexString(item.getArbitratorSignature())); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getMakerPenaltyFeeColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.maker.penalty.fee")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(HavenoUtils.formatXmr(item.getPenaltyAmount(), true)); - else - setText(""); - } - }; - } - }); - return column; - } - - private TableColumn<SignedOffer, SignedOffer> getReserveTxMinerFeeColumn() { - TableColumn<SignedOffer, SignedOffer> column = new AutoTooltipTableColumn<>(Res.get("support.tx.miner.fee")) { - { - setMinWidth(160); - } - }; - column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue())); - column.setCellFactory( - new Callback<>() { - @Override - public TableCell<SignedOffer, SignedOffer> call(TableColumn<SignedOffer, SignedOffer> column) { - return new TableCell<>() { - @Override - public void updateItem(final SignedOffer item, boolean empty) { - super.updateItem(item, empty); - if (item != null && !empty) - setText(HavenoUtils.formatXmr(item.getReserveTxMinerFee(), true)); - else - setText(""); - } - }; - } - }); - return column; - } -}