mirror of
https://github.com/boldsuck/haveno.git
synced 2024-12-22 12:09:22 +00:00
Update Signed Offers view in legacy UI
This commit is contained in:
parent
3b8f19c4ce
commit
4bef95172c
9 changed files with 525 additions and 445 deletions
8
.github/workflows/build.yml
vendored
8
.github/workflows/build.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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"/>
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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())));
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue