mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Fix pending trades view update bugs
This commit is contained in:
parent
0ac6b39270
commit
b416408f89
4 changed files with 89 additions and 52 deletions
|
@ -21,13 +21,13 @@ import io.bitsquare.btc.AddressEntry;
|
|||
import io.bitsquare.btc.FeePolicy;
|
||||
import io.bitsquare.btc.WalletService;
|
||||
import io.bitsquare.btc.listeners.TxConfidenceListener;
|
||||
import io.bitsquare.common.viewfx.model.Activatable;
|
||||
import io.bitsquare.common.viewfx.model.DataModel;
|
||||
import io.bitsquare.offer.Direction;
|
||||
import io.bitsquare.offer.Offer;
|
||||
import io.bitsquare.trade.Trade;
|
||||
import io.bitsquare.trade.TradeManager;
|
||||
import io.bitsquare.user.User;
|
||||
import io.bitsquare.common.viewfx.model.Activatable;
|
||||
import io.bitsquare.common.viewfx.model.DataModel;
|
||||
|
||||
import org.bitcoinj.core.AddressFormatException;
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
@ -39,9 +39,9 @@ import com.google.common.util.concurrent.FutureCallback;
|
|||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
@ -67,14 +67,14 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
private PendingTradesListItem selectedItem;
|
||||
private boolean isOfferer;
|
||||
private Trade closedTrade;
|
||||
private TxConfidenceListener txConfidenceListener;
|
||||
|
||||
private final ChangeListener<Trade.State> stateChangeListener;
|
||||
private TxConfidenceListener txConfidenceListener;
|
||||
private final ChangeListener<Trade.State> tradeStateChangeListener;
|
||||
private final MapChangeListener<String, Trade> mapChangeListener;
|
||||
|
||||
final StringProperty txId = new SimpleStringProperty();
|
||||
final ObjectProperty<Trade.State> tradeState = new SimpleObjectProperty<>();
|
||||
|
||||
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
|
||||
|
||||
@Inject
|
||||
public PendingTradesDataModel(TradeManager tradeManager, WalletService walletService, User user) {
|
||||
|
@ -82,13 +82,23 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
this.walletService = walletService;
|
||||
this.user = user;
|
||||
|
||||
this.stateChangeListener = (ov, oldValue, newValue) -> tradeState.set(newValue);
|
||||
tradeStateChangeListener = (ov, oldValue, newValue) -> tradeState.set(newValue);
|
||||
|
||||
this.mapChangeListener = change -> {
|
||||
if (change.wasAdded())
|
||||
mapChangeListener = change -> {
|
||||
if (change.wasAdded()) {
|
||||
list.add(new PendingTradesListItem(change.getValueAdded()));
|
||||
else if (change.wasRemoved())
|
||||
if (list.size() == 1) {
|
||||
selectTrade(list.get(0));
|
||||
selectedIndex.set(0);
|
||||
}
|
||||
}
|
||||
else if (change.wasRemoved()) {
|
||||
closedTrade = change.getValueRemoved();
|
||||
if (list.size() == 0) {
|
||||
selectTrade(null);
|
||||
selectedIndex.set(-1);
|
||||
}
|
||||
}
|
||||
|
||||
sortList();
|
||||
};
|
||||
|
@ -98,27 +108,33 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
public void activate() {
|
||||
list.clear();
|
||||
// transform trades to list of PendingTradesListItems and keep it updated
|
||||
tradeManager.getPendingTrades().values().stream()
|
||||
.forEach(e -> list.add(new PendingTradesListItem(e)));
|
||||
tradeManager.getPendingTrades().values().stream().forEach(e -> list.add(new PendingTradesListItem(e)));
|
||||
tradeManager.getPendingTrades().addListener(mapChangeListener);
|
||||
|
||||
// we sort by date, earliest first
|
||||
sortList();
|
||||
|
||||
// select either currentPendingTrade or first in the list
|
||||
Optional<PendingTradesListItem> currentTradeItemOptional = list.stream()
|
||||
.filter((e) -> tradeManager.getCurrentPendingTrade() != null &&
|
||||
tradeManager.getCurrentPendingTrade().getId().equals(e.getTrade().getId()))
|
||||
.findFirst();
|
||||
if (currentTradeItemOptional.isPresent())
|
||||
selectTrade(currentTradeItemOptional.get());
|
||||
else if (list.size() > 0)
|
||||
if (tradeManager.getCurrentPendingTrade() != null) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
PendingTradesListItem item = list.get(i);
|
||||
if (tradeManager.getCurrentPendingTrade().getId().equals(item.getTrade().getId())) {
|
||||
selectedIndex.set(i);
|
||||
selectTrade(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (list.size() > 0) {
|
||||
selectTrade(list.get(0));
|
||||
selectedIndex.set(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
tradeManager.getPendingTrades().removeListener(mapChangeListener);
|
||||
|
||||
cleanUpSelectedTrade();
|
||||
}
|
||||
|
||||
|
@ -133,7 +149,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
isOfferer = getTrade().getOffer().getMessagePublicKey().equals(user.getMessagePubKey());
|
||||
|
||||
Trade trade = getTrade();
|
||||
trade.stateProperty().addListener(stateChangeListener);
|
||||
trade.stateProperty().addListener(tradeStateChangeListener);
|
||||
tradeState.set(trade.stateProperty().get());
|
||||
log.trace("selectTrade trade.stateProperty().get() " + trade.stateProperty().get());
|
||||
|
||||
|
@ -287,8 +303,7 @@ class PendingTradesDataModel implements Activatable, DataModel {
|
|||
|
||||
private void cleanUpSelectedTrade() {
|
||||
if (selectedItem != null) {
|
||||
Trade trade = getTrade();
|
||||
trade.stateProperty().removeListener(stateChangeListener);
|
||||
selectedItem.getTrade().stateProperty().removeListener(tradeStateChangeListener);
|
||||
}
|
||||
|
||||
if (txConfidenceListener != null)
|
||||
|
|
|
@ -82,13 +82,15 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
|
|||
@FXML TableColumn<PendingTradesListItem, Date> dateColumn;
|
||||
@FXML TableColumn<PendingTradesListItem, Coin> tradeAmountColumn;
|
||||
|
||||
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
|
||||
private ChangeListener<Number> selectedIndexChangeListener;
|
||||
private ListChangeListener<PendingTradesListItem> listChangeListener;
|
||||
private ChangeListener<String> txIdChangeListener;
|
||||
private ChangeListener<PendingTradesViewModel.State> offererStateChangeListener;
|
||||
private ChangeListener<PendingTradesViewModel.State> takerStateChangeListener;
|
||||
|
||||
private final Navigation navigation;
|
||||
private ChangeListener<Boolean> focusedPropertyListener;
|
||||
private ChangeListener<PendingTradesListItem> selectedItemChangeListener;
|
||||
|
||||
@Inject
|
||||
public PendingTradesView(PendingTradesViewModel model, Navigation navigation) {
|
||||
|
@ -112,60 +114,68 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
|
|||
table.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
table.setPlaceholder(new Label("No pending trades available"));
|
||||
|
||||
txIdChangeListener = (ov, oldValue, newValue) ->
|
||||
txIdTextField.setup(model.getWalletService(), newValue);
|
||||
txIdChangeListener = (ov, oldValue, newValue) -> txIdTextField.setup(model.getWalletService(), newValue);
|
||||
|
||||
selectedItemChangeListener = (obsValue, oldValue, newValue) -> {
|
||||
if (oldValue != null && newValue != null) {
|
||||
model.selectTrade(newValue);
|
||||
updateScreen();
|
||||
}
|
||||
selectedIndexChangeListener = (ov, oldValue, newValue) -> {
|
||||
if ((Integer) newValue > -1)
|
||||
table.getSelectionModel().select((Integer) newValue);
|
||||
|
||||
updateScreen();
|
||||
};
|
||||
|
||||
listChangeListener = change -> {
|
||||
change.next();
|
||||
if ((change.wasAdded() && change.getList().size() == 1) ||
|
||||
(change.wasRemoved() && change.getList().size() == 0))
|
||||
|
||||
updateScreen();
|
||||
};
|
||||
|
||||
offererStateChangeListener = (ov, oldValue, newValue) -> applyOffererState(newValue);
|
||||
takerStateChangeListener = (ov, oldValue, newValue) -> applyTakerState(newValue);
|
||||
|
||||
focusedPropertyListener = (ov, oldValue, newValue) -> {
|
||||
if (oldValue && !newValue)
|
||||
model.withdrawAddressFocusOut(withdrawAddressTextField.getText());
|
||||
};
|
||||
selectedItemChangeListener = (ov, oldValue, newValue) -> {
|
||||
model.selectTrade(newValue);
|
||||
updateScreen();
|
||||
};
|
||||
|
||||
withdrawAddressTextField.setValidator(model.getBtcAddressValidator());
|
||||
withdrawButton.disableProperty().bind(model.withdrawalButtonDisable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doActivate() {
|
||||
table.setItems(model.getList());
|
||||
|
||||
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
|
||||
model.getList().addListener(listChangeListener);
|
||||
model.txId.addListener(txIdChangeListener);
|
||||
model.selectedIndex.addListener(selectedIndexChangeListener);
|
||||
withdrawAddressTextField.focusedProperty().addListener(focusedPropertyListener);
|
||||
|
||||
txIdTextField.setup(model.getWalletService(), model.txId.get());
|
||||
table.getSelectionModel().select(model.getSelectedItem());
|
||||
table.getSelectionModel().selectedItemProperty().addListener(selectedItemChangeListener);
|
||||
|
||||
// TODO Set focus to row does not work yet...
|
||||
/* table.requestFocus();
|
||||
table.getFocusModel().focus( table.getSelectionModel().getSelectedIndex());*/
|
||||
Platform.runLater(() -> table.requestFocus());
|
||||
table.getFocusModel().focus(model.selectedIndex.get());
|
||||
txIdTextField.setup(model.getWalletService(), model.txId.get());
|
||||
selectedIndexChangeListener.changed(null, null, model.selectedIndex.get());
|
||||
|
||||
withdrawAddressTextField.focusedProperty().addListener((ov, oldValue, newValue) -> {
|
||||
if (oldValue && !newValue)
|
||||
model.withdrawAddressFocusOut(withdrawAddressTextField.getText());
|
||||
});
|
||||
withdrawButton.disableProperty().bind(model.withdrawalButtonDisable);
|
||||
updateScreen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doDeactivate() {
|
||||
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
|
||||
model.getList().removeListener(listChangeListener);
|
||||
model.txId.removeListener(txIdChangeListener);
|
||||
|
||||
model.state.removeListener(offererStateChangeListener);
|
||||
model.state.removeListener(takerStateChangeListener);
|
||||
model.selectedIndex.removeListener(selectedIndexChangeListener);
|
||||
table.getSelectionModel().selectedItemProperty().removeListener(selectedItemChangeListener);
|
||||
|
||||
withdrawButton.disableProperty().unbind();
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
@ -450,7 +460,8 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
|
|||
fiatAmountTextField.setManaged(visible);
|
||||
holderNameTextField.setManaged(visible);
|
||||
|
||||
Platform.runLater(() -> scrollPane.setVvalue(visible ? scrollPane.getVmax() : 0));
|
||||
if (visible)
|
||||
Platform.runLater(() -> scrollPane.setVvalue(scrollPane.getVmax()));
|
||||
}
|
||||
|
||||
private void setSummaryControlsVisible(boolean visible) {
|
||||
|
@ -491,11 +502,14 @@ public class PendingTradesView extends ActivatableViewAndModel<AnchorPane, Pendi
|
|||
withdrawButton.setManaged(visible);
|
||||
|
||||
if (visible)
|
||||
withdrawAddressTextField.requestFocus();
|
||||
|
||||
Platform.runLater(() -> scrollPane.setVvalue(visible ? scrollPane.getVmax() : 0));
|
||||
Platform.runLater(() -> {
|
||||
withdrawAddressTextField.requestFocus();
|
||||
scrollPane.setVvalue(scrollPane.getVmax());
|
||||
});
|
||||
}
|
||||
|
||||
// CellFactories
|
||||
|
||||
private void setTradeIdColumnCellFactory() {
|
||||
idColumn.setCellFactory(
|
||||
new Callback<TableColumn<PendingTradesListItem, String>, TableCell<PendingTradesListItem, String>>() {
|
||||
|
|
|
@ -34,8 +34,10 @@ import java.util.Date;
|
|||
|
||||
import javafx.beans.InvalidationListener;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
import javafx.beans.property.StringProperty;
|
||||
|
@ -66,6 +68,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
|||
final StringProperty txId = new SimpleStringProperty();
|
||||
final ObjectProperty<State> state = new SimpleObjectProperty<>();
|
||||
final BooleanProperty withdrawalButtonDisable = new SimpleBooleanProperty(true);
|
||||
final IntegerProperty selectedIndex = new SimpleIntegerProperty(-1);
|
||||
|
||||
|
||||
@Inject
|
||||
|
@ -81,6 +84,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
|||
@Override
|
||||
public void doActivate() {
|
||||
txId.bind(dataModel.txId);
|
||||
selectedIndex.bind(dataModel.selectedIndex);
|
||||
|
||||
dataModel.tradeState.addListener(stateChangeListener);
|
||||
updateState();
|
||||
|
@ -89,6 +93,7 @@ class PendingTradesViewModel extends ActivatableWithDataModel<PendingTradesDataM
|
|||
@Override
|
||||
public void doDeactivate() {
|
||||
txId.unbind();
|
||||
selectedIndex.unbind();
|
||||
|
||||
dataModel.tradeState.removeListener(stateChangeListener);
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ import io.bitsquare.user.User;
|
|||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.utils.Fiat;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -102,17 +104,17 @@ public class TradeManager {
|
|||
this.signatureService = signatureService;
|
||||
this.offerBookService = offerBookService;
|
||||
|
||||
Object openOffersObject = persistence.read(this, "openOffers");
|
||||
Serializable openOffersObject = persistence.read(this, "openOffers");
|
||||
if (openOffersObject instanceof Map<?, ?>) {
|
||||
openOffers.putAll((Map<String, Offer>) openOffersObject);
|
||||
}
|
||||
|
||||
Object pendingTradesObject = persistence.read(this, "pendingTrades");
|
||||
Serializable pendingTradesObject = persistence.read(this, "pendingTrades");
|
||||
if (pendingTradesObject instanceof Map<?, ?>) {
|
||||
pendingTrades.putAll((Map<String, Trade>) pendingTradesObject);
|
||||
}
|
||||
|
||||
Object closedTradesObject = persistence.read(this, "closedTrades");
|
||||
Serializable closedTradesObject = persistence.read(this, "closedTrades");
|
||||
if (closedTradesObject instanceof Map<?, ?>) {
|
||||
closedTrades.putAll((Map<String, Trade>) closedTradesObject);
|
||||
}
|
||||
|
@ -120,7 +122,8 @@ public class TradeManager {
|
|||
tradeMessageService.addMessageHandler(this::handleMessage);
|
||||
}
|
||||
|
||||
// When all services are initialized we create the protocols for our open offers (which will listen for take offer requests)
|
||||
// When all services are initialized we create the protocols for our open offers and persisted not completed pendingTrades
|
||||
// BuyerAcceptsOfferProtocol listens for take offer requests, so we need to instantiate it early.
|
||||
public void onAllServicesInitialized() {
|
||||
for (Map.Entry<String, Offer> entry : openOffers.entrySet()) {
|
||||
createBuyerAcceptsOfferProtocol(entry.getValue());
|
||||
|
|
Loading…
Add table
Reference in a new issue