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 .
+ */
+
+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 .
-->
-
-
+
+
+
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 .
+ */
+
+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 {
+
+ @FXML
+ FilterBox filterBox;
+ @FXML
+ protected TableView tableView;
+ @FXML
+ TableColumn dateColumn;
+ @FXML
+ TableColumn traderIdColumn;
+ @FXML
+ TableColumn offerIdColumn;
+ @FXML
+ TableColumn reserveTxKeyImages;
+ @FXML
+ TableColumn 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 filteredList = new FilteredList<>(model.getList());
+ SortedList 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 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 getDateColumn() {
+ TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.date")) {
+ {
+ setMinWidth(180);
+ }
+ };
+ column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
+ column.setCellFactory(
+ new Callback<>() {
+ @Override
+ public TableCell call(TableColumn 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 getTraderIdColumn() {
+ TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.traderId")) {
+ {
+ setMinWidth(110);
+ }
+ };
+ column.setCellValueFactory(signedOffer -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
+ column.setCellFactory(
+ new Callback<>() {
+ @Override
+ public TableCell call(TableColumn 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 getOfferIdColumn() {
+ TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) {
+ {
+ setMinWidth(110);
+ }
+ };
+ column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
+ column.setCellFactory(
+ new Callback<>() {
+ @Override
+ public TableCell call(TableColumn 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 getMakerPenaltyFeeColumn() {
+ TableColumn 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 call(TableColumn 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 getReserveTxKeyImagesColumn() {
+ TableColumn column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) {
+ {
+ setMinWidth(160);
+ }
+ };
+ column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
+ column.setCellFactory(
+ new Callback<>() {
+ @Override
+ public TableCell call(TableColumn 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 .
+ */
+
+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 list = FXCollections.observableArrayList();
+ private final ListChangeListener 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 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 .
+ */
+
+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 implements ViewModel {
+
+ @Inject
+ public SignedOffersViewModel(SignedOffersDataModel model) {
+ super(model);
+ }
+
+ public ObservableList 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 .
- */
-
-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 {
-
- private final OpenOfferManager openOfferManager;
-
- @FXML
- protected TableView tableView;
- @FXML
- TableColumn dateColumn;
- @FXML
- TableColumn offerIdColumn;
- @FXML
- TableColumn reserveTxHashColumn;
- @FXML
- TableColumn reserveTxHexColumn;
- @FXML
- TableColumn reserveTxKeyImages;
- @FXML
- TableColumn arbitratorSignatureColumn;
- @FXML
- TableColumn reserveTxMinerFeeColumn;
- @FXML
- TableColumn makerPenaltyFeeColumn;
- @FXML
- InputTextField filterTextField;
- @FXML
- Label numItems;
- @FXML
- Region footerSpacer;
-
- private SignedOffer selectedSignedOffer;
-
- private XmrWalletService xmrWalletService;
-
- private ContextMenu contextMenu;
-
- private final ListChangeListener signedOfferListChangeListener;
-
- @Inject
- public SignedOfferView(OpenOfferManager openOfferManager, XmrWalletService xmrWalletService) {
- this.openOfferManager = openOfferManager;
- this.xmrWalletService = xmrWalletService;
-
- signedOfferListChangeListener = change -> applyList();
- }
-
- private void applyList() {
- UserThread.execute(() -> {
- SortedList 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 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 getDateColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.date")) {
- {
- setMinWidth(180);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getOfferIdColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("shared.offerId")) {
- {
- setMinWidth(110);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getReserveTxHashColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("support.txHash")) {
- {
- setMinWidth(160);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getReserveTxHexColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("support.txHex")) {
- {
- setMinWidth(160);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getReserveTxKeyImagesColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("support.txKeyImages")) {
- {
- setMinWidth(160);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getArbitratorSignatureColumn() {
- TableColumn column = new AutoTooltipTableColumn<>(Res.get("support.signature")) {
- {
- setMinWidth(160);
- }
- };
- column.setCellValueFactory((signedOffer) -> new ReadOnlyObjectWrapper<>(signedOffer.getValue()));
- column.setCellFactory(
- new Callback<>() {
- @Override
- public TableCell call(TableColumn 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 getMakerPenaltyFeeColumn() {
- TableColumn 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 call(TableColumn 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 getReserveTxMinerFeeColumn() {
- TableColumn 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 call(TableColumn 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;
- }
-}