mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 15:10:44 +01:00
Cleanup bond views
This commit is contained in:
parent
ceee3562af
commit
698d01d4be
22 changed files with 484 additions and 913 deletions
|
@ -27,7 +27,6 @@ import bisq.core.dao.governance.blindvote.MyBlindVoteListService;
|
|||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupReason;
|
||||
import bisq.core.dao.governance.bond.lockup.LockupTxService;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputationRepository;
|
||||
|
@ -291,7 +290,7 @@ public class DaoFacade implements DaoSetupService {
|
|||
return removeAssetProposalFactory.createProposalWithTransaction(name, link, asset);
|
||||
}
|
||||
|
||||
public List<BondedRole> getBondedRoles() {
|
||||
public ObservableList<BondedRole> getBondedRoles() {
|
||||
return bondedRolesRepository.getBonds();
|
||||
}
|
||||
|
||||
|
@ -518,19 +517,14 @@ public class DaoFacade implements DaoSetupService {
|
|||
return daoStateService.getLockTime(txId);
|
||||
}
|
||||
|
||||
public List<BondedRole> getActiveBondedRoles() {
|
||||
return bondedRolesRepository.getActiveBonds();
|
||||
}
|
||||
|
||||
public List<Bond> getAllBonds() {
|
||||
List<BondedReputation> bondedReputations = bondedReputationRepository.getBonds();
|
||||
List<BondedRole> bondedRoles = bondedRolesRepository.getBonds();
|
||||
List<Bond> bonds = new ArrayList<>(bondedReputations);
|
||||
bonds.addAll(bondedRoles);
|
||||
List<Bond> bonds = new ArrayList<>(bondedReputationRepository.getBonds());
|
||||
bonds.addAll(bondedRolesRepository.getBonds());
|
||||
return bonds;
|
||||
}
|
||||
|
||||
public List<MyBondedReputation> getMyBondedReputations() {
|
||||
public ObservableList<MyBondedReputation> getMyBondedReputations() {
|
||||
return myBondedReputationRepository.getMyBondedReputations();
|
||||
}
|
||||
|
||||
|
@ -665,6 +659,6 @@ public class DaoFacade implements DaoSetupService {
|
|||
}
|
||||
|
||||
public Optional<Bond> getBondByLockupTxId(String lockupTxId) {
|
||||
return getAllBonds().stream().filter(e -> e.getLockupTxId().equals(lockupTxId)).findAny();
|
||||
return getAllBonds().stream().filter(e -> lockupTxId.equals(e.getLockupTxId())).findAny();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,22 +34,26 @@ import org.bitcoinj.core.TransactionOutput;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Collect bonds and bond asset data from other sources and provides access to the collection.
|
||||
* Gets updated after a new block is parsed or at bsqWallet transaction change to detect also state changes by
|
||||
* unconfirmed txs.
|
||||
*/
|
||||
@Slf4j
|
||||
public abstract class BondRepository<T extends Bond, R extends BondedAsset> implements DaoStateListener, DaoSetupService {
|
||||
public abstract class BondRepository<T extends Bond, R extends BondedAsset> implements DaoSetupService {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Static
|
||||
|
@ -129,6 +133,8 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
|
||||
// This map is just for convenience. The data which are used to fill the map are stored in the DaoState (role, txs).
|
||||
protected final Map<String, T> bondByUidMap = new HashMap<>();
|
||||
@Getter
|
||||
protected final ObservableList<T> bonds = FXCollections.observableArrayList();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -139,8 +145,6 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
public BondRepository(DaoStateService daoStateService, BsqWalletService bsqWalletService) {
|
||||
this.daoStateService = daoStateService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
|
||||
daoStateService.addBsqStateListener(this);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -149,30 +153,26 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
daoStateService.addBsqStateListener(new DaoStateListener() {
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
});
|
||||
bsqWalletService.getWalletTransactions().addListener((ListChangeListener<Transaction>) c -> update());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
updateMap();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
// TODO optimize to not re-write the whole map at each block
|
||||
updateMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
|
@ -180,20 +180,9 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
// API
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<T> getBonds() {
|
||||
return new ArrayList<>(bondByUidMap.values());
|
||||
}
|
||||
|
||||
public List<T> getActiveBonds() {
|
||||
return bondByUidMap.values().stream()
|
||||
.filter(T::isActive)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public boolean isBondedAssetAlreadyInBond(R bondedAsset) {
|
||||
boolean contains = bondByUidMap.containsKey(bondedAsset.getUid());
|
||||
return contains && bondByUidMap.get(bondedAsset.getUid()).getLockupTxId() != null;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -207,7 +196,7 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
|
||||
abstract protected Stream<R> getBondedAssetStream();
|
||||
|
||||
protected void updateMap() {
|
||||
protected void update() {
|
||||
getBondedAssetStream().forEach(bondedAsset -> {
|
||||
String uid = bondedAsset.getUid();
|
||||
bondByUidMap.putIfAbsent(uid, createBond(bondedAsset));
|
||||
|
@ -220,6 +209,8 @@ public abstract class BondRepository<T extends Bond, R extends BondedAsset> impl
|
|||
|
||||
updateBondStateFromUnconfirmedLockupTxs();
|
||||
updateBondStateFromUnconfirmedUnlockTxs();
|
||||
|
||||
bonds.setAll(bondByUidMap.values());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -21,12 +21,15 @@ import bisq.core.btc.wallet.BsqWalletService;
|
|||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.BondRepository;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.TxOutput;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
@ -38,6 +41,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||
/**
|
||||
* Collect bonded reputations from the daoState blockchain data excluding bonded roles
|
||||
* and provides access to the collection.
|
||||
* Gets updated after a new block is parsed or at bsqWallet transaction change to detect also state changes by
|
||||
* unconfirmed txs.
|
||||
*/
|
||||
@Slf4j
|
||||
public class BondedReputationRepository extends BondRepository<BondedReputation, Reputation> {
|
||||
|
@ -55,6 +60,25 @@ public class BondedReputationRepository extends BondRepository<BondedReputation,
|
|||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoSetupService
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
super.addListeners();
|
||||
|
||||
// As event listeners do not have a deterministic ordering of callback we need to ensure
|
||||
// that we get updated our data after the bondedRolesRepository was updated.
|
||||
// The update gets triggered by daoState or wallet changes. It could be that we get triggered first the
|
||||
// listeners and update our data with stale data from bondedRolesRepository. After that the bondedRolesRepository
|
||||
// gets triggered the listeners and we would miss the current state if we would not listen here as well on the
|
||||
// bond list.
|
||||
bondedRolesRepository.getBonds().addListener((ListChangeListener<BondedRole>) c -> {
|
||||
update();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Protected
|
||||
|
@ -71,9 +95,10 @@ public class BondedReputationRepository extends BondRepository<BondedReputation,
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void updateMap() {
|
||||
protected void update() {
|
||||
bondByUidMap.clear();
|
||||
getBondedReputationStream().forEach(bondedReputation -> bondByUidMap.put(bondedReputation.getBondedAsset().getUid(), bondedReputation));
|
||||
bonds.setAll(bondByUidMap.values());
|
||||
}
|
||||
|
||||
private Stream<BondedReputation> getBondedReputationStream() {
|
||||
|
@ -97,7 +122,7 @@ public class BondedReputationRepository extends BondRepository<BondedReputation,
|
|||
}
|
||||
|
||||
private Stream<TxOutput> getLockupTxOutputsForBondedReputation() {
|
||||
// We exclude bonded roles, so we store those ina lookup set.
|
||||
// We exclude bonded roles, so we store those in a lookup set.
|
||||
Set<String> bondedRolesLockupTxIdSet = bondedRolesRepository.getBonds().stream().map(Bond::getLockupTxId).collect(Collectors.toSet());
|
||||
return daoStateService.getLockupTxOutputs().stream()
|
||||
.filter(e -> !bondedRolesLockupTxIdSet.contains(e.getTxId()));
|
||||
|
|
|
@ -22,28 +22,41 @@ import bisq.core.dao.DaoSetupService;
|
|||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.governance.bond.BondRepository;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.DaoStateService;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* Collect MyBondedReputations from the myReputationListService and provides access to the collection.
|
||||
* Gets updated after a new block is parsed or at bsqWallet transaction change to detect also state changes by
|
||||
* unconfirmed txs.
|
||||
*/
|
||||
@Slf4j
|
||||
//TODO maybe extend BondRepository as well?
|
||||
public class MyBondedReputationRepository implements DaoSetupService {
|
||||
private final DaoStateService daoStateService;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final MyReputationListService myReputationListService;
|
||||
@Getter
|
||||
private final ObservableList<MyBondedReputation> myBondedReputations = FXCollections.observableArrayList();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -66,6 +79,21 @@ public class MyBondedReputationRepository implements DaoSetupService {
|
|||
|
||||
@Override
|
||||
public void addListeners() {
|
||||
daoStateService.addBsqStateListener(new DaoStateListener() {
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
});
|
||||
bsqWalletService.getWalletTransactions().addListener((ListChangeListener<Transaction>) c -> update());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,10 +102,10 @@ public class MyBondedReputationRepository implements DaoSetupService {
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// API
|
||||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public List<MyBondedReputation> getMyBondedReputations() {
|
||||
private void update() {
|
||||
// It can be that the same salt/hash is in several lockupTxs, so we use the bondByLockupTxIdMap to eliminate
|
||||
// duplicates by the collection algorithm.
|
||||
Map<String, MyBondedReputation> bondByLockupTxIdMap = new HashMap<>();
|
||||
|
@ -85,7 +113,7 @@ public class MyBondedReputationRepository implements DaoSetupService {
|
|||
.flatMap(this::getMyBondedReputation)
|
||||
.forEach(e -> bondByLockupTxIdMap.putIfAbsent(e.getLockupTxId(), e));
|
||||
|
||||
return bondByLockupTxIdMap.values().stream()
|
||||
myBondedReputations.setAll(bondByLockupTxIdMap.values().stream()
|
||||
.peek(myBondedReputation -> {
|
||||
if (BondRepository.isConfiscated(myBondedReputation, daoStateService)) {
|
||||
myBondedReputation.setBondState(BondState.CONFISCATED);
|
||||
|
@ -101,7 +129,7 @@ public class MyBondedReputationRepository implements DaoSetupService {
|
|||
}
|
||||
}
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private Stream<MyBondedReputation> getMyBondedReputation(MyReputation myReputation) {
|
||||
|
|
|
@ -37,6 +37,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
|
||||
/**
|
||||
* MyReputation is persisted locally and carries the private salt data. In contrast to Reputation which is the public
|
||||
* data everyone can derive from the blockchain data (hash in opReturn).
|
||||
|
@ -52,6 +54,7 @@ public final class MyReputation implements PersistablePayload, NetworkPayload, B
|
|||
|
||||
public MyReputation(byte[] salt) {
|
||||
this(UUID.randomUUID().toString(), salt);
|
||||
checkArgument(salt.length <= 20, "salt must not be longer then 20 bytes");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -26,9 +26,7 @@ import bisq.common.storage.Storage;
|
|||
import javax.inject.Inject;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
|
@ -37,17 +35,9 @@ import lombok.extern.slf4j.Slf4j;
|
|||
@Slf4j
|
||||
public class MyReputationListService implements PersistedDataHost, DaoSetupService {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
interface MyReputationListChangeListener {
|
||||
void onListChanged(List<MyReputation> list);
|
||||
}
|
||||
|
||||
private final Storage<MyReputationList> storage;
|
||||
private final MyReputationList myReputationList = new MyReputationList();
|
||||
|
||||
@Getter
|
||||
private final List<MyReputationListChangeListener> listeners = new CopyOnWriteArrayList<>();
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor
|
||||
|
@ -70,7 +60,6 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi
|
|||
if (persisted != null) {
|
||||
myReputationList.clear();
|
||||
myReputationList.addAll(persisted.getList());
|
||||
listeners.forEach(l -> l.onListChanged(myReputationList.getList()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -103,11 +92,6 @@ public class MyReputationListService implements PersistedDataHost, DaoSetupServi
|
|||
return myReputationList.getList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public void addListener(MyReputationListChangeListener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private
|
||||
|
|
|
@ -29,8 +29,8 @@ import bisq.desktop.main.MainView;
|
|||
import bisq.desktop.main.dao.DaoView;
|
||||
import bisq.desktop.main.dao.bonding.bonds.BondsView;
|
||||
import bisq.desktop.main.dao.bonding.dashboard.BondingDashboardView;
|
||||
import bisq.desktop.main.dao.bonding.reputation.MyBondedReputationView;
|
||||
import bisq.desktop.main.dao.bonding.roles.BondedRolesView;
|
||||
import bisq.desktop.main.dao.bonding.reputation.MyReputationView;
|
||||
import bisq.desktop.main.dao.bonding.roles.RolesView;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
|
@ -84,9 +84,9 @@ public class BondingView extends ActivatableViewAndModel {
|
|||
dashboard = new MenuItem(navigation, toggleGroup, Res.get("shared.dashboard"),
|
||||
BondingDashboardView.class, AwesomeIcon.DASHBOARD, baseNavPath);
|
||||
bondedRoles = new MenuItem(navigation, toggleGroup, Res.get("dao.bonding.menuItem.bondedRoles"),
|
||||
BondedRolesView.class, AwesomeIcon.SHIELD, baseNavPath);
|
||||
RolesView.class, AwesomeIcon.SHIELD, baseNavPath);
|
||||
reputation = new MenuItem(navigation, toggleGroup, Res.get("dao.bonding.menuItem.reputation"),
|
||||
MyBondedReputationView.class, AwesomeIcon.LOCK, baseNavPath);
|
||||
MyReputationView.class, AwesomeIcon.LOCK, baseNavPath);
|
||||
bonds = new MenuItem(navigation, toggleGroup, Res.get("dao.bonding.menuItem.bonds"),
|
||||
BondsView.class, AwesomeIcon.UNLOCK, baseNavPath);
|
||||
|
||||
|
@ -105,7 +105,7 @@ public class BondingView extends ActivatableViewAndModel {
|
|||
if (viewPath.size() == 3 && viewPath.indexOf(BondingView.class) == 2 ||
|
||||
viewPath.size() == 2 && viewPath.indexOf(DaoView.class) == 1) {
|
||||
if (selectedViewClass == null)
|
||||
selectedViewClass = BondedRolesView.class;
|
||||
selectedViewClass = RolesView.class;
|
||||
|
||||
loadView(selectedViewClass);
|
||||
|
||||
|
@ -115,6 +115,7 @@ public class BondingView extends ActivatableViewAndModel {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("Duplicates")
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
navigation.removeListener(listener);
|
||||
|
@ -130,8 +131,8 @@ public class BondingView extends ActivatableViewAndModel {
|
|||
content.getChildren().setAll(view.getRoot());
|
||||
|
||||
if (view instanceof BondingDashboardView) dashboard.setSelected(true);
|
||||
else if (view instanceof BondedRolesView) bondedRoles.setSelected(true);
|
||||
else if (view instanceof MyBondedReputationView) reputation.setSelected(true);
|
||||
else if (view instanceof RolesView) bondedRoles.setSelected(true);
|
||||
else if (view instanceof MyReputationView) reputation.setSelected(true);
|
||||
else if (view instanceof BondsView) bonds.setSelected(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,14 +17,9 @@
|
|||
|
||||
package bisq.desktop.main.dao.bonding.bonds;
|
||||
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
|
@ -32,47 +27,27 @@ import bisq.common.util.Utilities;
|
|||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Data
|
||||
@Value
|
||||
@Slf4j
|
||||
class BondListItem implements DaoStateListener {
|
||||
class BondListItem {
|
||||
private final Bond bond;
|
||||
private final DaoFacade daoFacade;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final String bondType;
|
||||
private final String txId;
|
||||
private final String lockupTxId;
|
||||
private final String amount;
|
||||
private final String lockupDate;
|
||||
private final String lockupDateString;
|
||||
private final String lockTime;
|
||||
private final Label stateLabel;
|
||||
private final String bondDetails;
|
||||
private final BondState bondState;
|
||||
private final String bondStateString;
|
||||
private final Date lockupDate;
|
||||
|
||||
@Getter
|
||||
private Button button;
|
||||
|
||||
BondListItem(Bond bond,
|
||||
DaoFacade daoFacade,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
BsqFormatter bsqFormatter) {
|
||||
BondListItem(Bond bond, BsqFormatter bsqFormatter) {
|
||||
this.bond = bond;
|
||||
this.daoFacade = daoFacade;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
|
||||
|
||||
amount = bsqFormatter.formatCoin(Coin.valueOf(bond.getAmount()));
|
||||
lockTime = Integer.toString(bond.getLockTime());
|
||||
|
@ -83,34 +58,10 @@ class BondListItem implements DaoStateListener {
|
|||
bondType = Res.get("dao.bond.bondedReputation");
|
||||
bondDetails = Utilities.bytesAsHexString(bond.getBondedAsset().getHash());
|
||||
}
|
||||
lockupDate = bsqFormatter.formatDateTime(new Date(bond.getLockupDate()));
|
||||
txId = bond.getLockupTxId();
|
||||
|
||||
stateLabel = new Label();
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
stateLabel.setText(Res.get("dao.bond.bondState." + bond.getBondState().name()));
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
}
|
||||
|
||||
// DaoStateListener
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
lockupTxId = bond.getLockupTxId();
|
||||
lockupDate = new Date(bond.getLockupDate());
|
||||
lockupDateString = bsqFormatter.formatDateTime(lockupDate);
|
||||
bondState = bond.getBondState();
|
||||
bondStateString = Res.get("dao.bond.bondState." + bond.getBondState().name());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,38 +21,29 @@ import bisq.desktop.common.view.ActivatableView;
|
|||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.validation.BsqValidator;
|
||||
|
||||
import bisq.core.btc.listeners.BsqBalanceListener;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.Bond;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.BondedReputationRepository;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.governance.bond.role.BondedRolesRepository;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
|
@ -61,22 +52,18 @@ import javafx.collections.transformation.SortedList;
|
|||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
@FxmlView
|
||||
public class BondsView extends ActivatableView<GridPane, Void> implements BsqBalanceListener, DaoStateListener {
|
||||
public class BondsView extends ActivatableView<GridPane, Void> {
|
||||
private TableView<BondListItem> tableView;
|
||||
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BsqValidator bsqValidator;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BondedRolesRepository bondedRolesRepository;
|
||||
private final DaoFacade daoFacade;
|
||||
private final BondedReputationRepository bondedReputationRepository;
|
||||
private final Preferences preferences;
|
||||
|
||||
private int gridRow = 0;
|
||||
|
@ -84,8 +71,8 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
private final ObservableList<BondListItem> observableList = FXCollections.observableArrayList();
|
||||
private final SortedList<BondListItem> sortedList = new SortedList<>(observableList);
|
||||
|
||||
private ListChangeListener<Transaction> walletBsqTransactionsListener;
|
||||
private ChangeListener<Number> walletChainHeightListener;
|
||||
private ListChangeListener<BondedRole> bondedRolesListener;
|
||||
private ListChangeListener<BondedReputation> bondedReputationListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -93,104 +80,39 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private BondsView(BsqWalletService bsqWalletService,
|
||||
BsqFormatter bsqFormatter,
|
||||
BsqValidator bsqValidator,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
private BondsView(BsqFormatter bsqFormatter,
|
||||
BondedRolesRepository bondedRolesRepository,
|
||||
DaoFacade daoFacade,
|
||||
BondedReputationRepository bondedReputationRepository,
|
||||
Preferences preferences) {
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.bsqValidator = bsqValidator;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.bondedRolesRepository = bondedRolesRepository;
|
||||
this.daoFacade = daoFacade;
|
||||
this.bondedReputationRepository = bondedReputationRepository;
|
||||
this.preferences = preferences;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
addTitledGroupBg(root, gridRow, 2, Res.get("dao.bonding.bonds.table.header"));
|
||||
|
||||
tableView = new TableView<>();
|
||||
GridPane.setRowIndex(tableView, ++gridRow);
|
||||
GridPane.setMargin(tableView, new Insets(30, -10, 5, -10));
|
||||
root.getChildren().add(tableView);
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bonding.bonds.table.header"));
|
||||
tableView.setItems(sortedList);
|
||||
addColumns();
|
||||
|
||||
walletBsqTransactionsListener = change -> updateList();
|
||||
walletChainHeightListener = (observable, oldValue, newValue) -> updateList();
|
||||
bondedReputationListener = c -> updateList();
|
||||
bondedRolesListener = c -> updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
onUpdateBalances(bsqWalletService.getAvailableBalance(),
|
||||
bsqWalletService.getAvailableNonBsqBalance(),
|
||||
bsqWalletService.getUnverifiedBalance(),
|
||||
bsqWalletService.getLockedForVotingBalance(),
|
||||
bsqWalletService.getLockupBondsBalance(),
|
||||
bsqWalletService.getUnlockingBondsBalance());
|
||||
|
||||
bsqWalletService.getWalletTransactions().addListener(walletBsqTransactionsListener);
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
bsqWalletService.getChainHeightProperty().addListener(walletChainHeightListener);
|
||||
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
bondedReputationRepository.getBonds().addListener(bondedReputationListener);
|
||||
bondedRolesRepository.getBonds().addListener(bondedRolesListener);
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
bsqWalletService.removeBsqBalanceListener(this);
|
||||
|
||||
bsqWalletService.getWalletTransactions().removeListener(walletBsqTransactionsListener);
|
||||
bsqWalletService.removeBsqBalanceListener(this);
|
||||
bsqWalletService.getChainHeightProperty().removeListener(walletChainHeightListener);
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
|
||||
sortedList.comparatorProperty().unbind();
|
||||
|
||||
observableList.forEach(BondListItem::cleanup);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BsqBalanceListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onUpdateBalances(Coin confirmedBalance,
|
||||
Coin availableNonBsqBalance,
|
||||
Coin pendingBalance,
|
||||
Coin lockedForVotingBalance,
|
||||
Coin lockupBondsBalance,
|
||||
Coin unlockingBondsBalance) {
|
||||
bsqValidator.setAvailableBalance(confirmedBalance);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
bondedReputationRepository.getBonds().removeListener(bondedReputationListener);
|
||||
bondedRolesRepository.getBonds().removeListener(bondedRolesListener);
|
||||
}
|
||||
|
||||
|
||||
|
@ -198,24 +120,16 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void openTxInBlockExplorer(BondListItem item) {
|
||||
if (item.getTxId() != null)
|
||||
GUIUtil.openWebPage(preferences.getBsqBlockChainExplorer().txUrl + item.getTxId());
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
List<BondListItem> items = daoFacade.getAllBonds().stream()
|
||||
List<Bond> combined = new ArrayList<>(bondedReputationRepository.getBonds());
|
||||
combined.addAll(bondedRolesRepository.getBonds());
|
||||
observableList.setAll(combined.stream()
|
||||
.map(bond -> {
|
||||
return new BondListItem(bond,
|
||||
daoFacade,
|
||||
bondedRolesRepository,
|
||||
bondingViewUtils,
|
||||
bsqFormatter);
|
||||
return new BondListItem(bond, bsqFormatter);
|
||||
})
|
||||
.sorted(Comparator.comparing(BondListItem::getLockupDate).reversed())
|
||||
.collect(Collectors.toList());
|
||||
observableList.setAll(items);
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 37, 28, 2, 10);
|
||||
.sorted(Comparator.comparing(BondListItem::getLockupDateString).reversed())
|
||||
.collect(Collectors.toList()));
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 37, 28, 2, 30);
|
||||
}
|
||||
|
||||
|
||||
|
@ -275,22 +189,14 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
public TableCell<BondListItem, BondListItem> call(TableColumn<BondListItem,
|
||||
BondListItem> column) {
|
||||
return new TableCell<>() {
|
||||
Label label;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (label == null) {
|
||||
label = item.getStateLabel();
|
||||
setGraphic(label);
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (label != null)
|
||||
label = null;
|
||||
}
|
||||
setText(item.getBondStateString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -341,10 +247,8 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.lockupDate"));
|
||||
column.setMinWidth(140);
|
||||
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondListItem, BondListItem> call(TableColumn<BondListItem, BondListItem> column) {
|
||||
return new TableCell<>() {
|
||||
|
@ -352,7 +256,7 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
public void updateItem(final BondListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getLockupDate());
|
||||
setText(item.getLockupDateString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
|
@ -366,7 +270,6 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
column.setMinWidth(60);
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondListItem, BondListItem> call(TableColumn<BondListItem,
|
||||
BondListItem> column) {
|
||||
|
@ -377,12 +280,11 @@ public class BondsView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
public void updateItem(final BondListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
//noinspection Duplicates
|
||||
if (item != null && !empty) {
|
||||
String transactionId = item.getTxId();
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(transactionId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(item));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", transactionId)));
|
||||
String lockupTxId = item.getLockupTxId();
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(lockupTxId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> GUIUtil.openTxInBsqBlockExplorer(lockupTxId, preferences));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", lockupTxId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
|
|
|
@ -1,128 +0,0 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.bonding.reputation;
|
||||
|
||||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputation;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@EqualsAndHashCode
|
||||
@Data
|
||||
@Slf4j
|
||||
class MyBondedReputationListItem implements DaoStateListener {
|
||||
private final MyBondedReputation myBondedReputation;
|
||||
private final DaoFacade daoFacade;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final String hash, salt;
|
||||
private final String txId;
|
||||
private final String amount;
|
||||
private final String lockupDate;
|
||||
private final String lockTime;
|
||||
|
||||
@Getter
|
||||
private final AutoTooltipButton button;
|
||||
@Getter
|
||||
private final Label stateLabel;
|
||||
|
||||
MyBondedReputationListItem(MyBondedReputation myBondedReputation,
|
||||
DaoFacade daoFacade,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.myBondedReputation = myBondedReputation;
|
||||
this.daoFacade = daoFacade;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
|
||||
MyReputation myReputation = myBondedReputation.getBondedAsset();
|
||||
hash = Utilities.bytesAsHexString(myReputation.getHash());
|
||||
salt = Utilities.bytesAsHexString(myReputation.getSalt());
|
||||
txId = myBondedReputation.getLockupTxId();
|
||||
amount = bsqFormatter.formatCoin(Coin.valueOf(myBondedReputation.getAmount()));
|
||||
lockupDate = bsqFormatter.formatDateTime(new Date(myBondedReputation.getLockupDate()));
|
||||
lockTime = Integer.toString(myBondedReputation.getLockTime());
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
button = new AutoTooltipButton();
|
||||
stateLabel = new Label();
|
||||
|
||||
button.setOnAction(e -> {
|
||||
if (myBondedReputation.getBondState() == BondState.LOCKUP_TX_CONFIRMED) {
|
||||
bondingViewUtils.unLock(myBondedReputation.getLockupTxId(),
|
||||
txId -> {
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
button.setOnAction(null);
|
||||
}
|
||||
|
||||
private void update() {
|
||||
stateLabel.setText(Res.get("dao.bond.bondState." + myBondedReputation.getBondState().name()));
|
||||
|
||||
boolean showButton = myBondedReputation.getBondState() == BondState.LOCKUP_TX_CONFIRMED;
|
||||
if (showButton)
|
||||
button.updateText(Res.get("dao.bond.table.button.unlock"));
|
||||
|
||||
button.setVisible(showButton);
|
||||
button.setManaged(showButton);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.bonding.reputation;
|
||||
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.dao.governance.bond.reputation.MyReputation;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Value;
|
||||
|
||||
@Value
|
||||
class MyReputationListItem {
|
||||
private final MyBondedReputation myBondedReputation;
|
||||
private final String hash, salt;
|
||||
private final String txId;
|
||||
private final String amount;
|
||||
private final String lockupDateString;
|
||||
private final String lockTime;
|
||||
|
||||
private final String buttonText;
|
||||
private final boolean showButton;
|
||||
private final BondState bondState;
|
||||
private final String bondStateString;
|
||||
private final String lockupTxId;
|
||||
private final Date lockupDate;
|
||||
|
||||
MyReputationListItem(MyBondedReputation myBondedReputation,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.myBondedReputation = myBondedReputation;
|
||||
|
||||
MyReputation myReputation = myBondedReputation.getBondedAsset();
|
||||
hash = Utilities.bytesAsHexString(myReputation.getHash());
|
||||
salt = Utilities.bytesAsHexString(myReputation.getSalt());
|
||||
txId = myBondedReputation.getLockupTxId();
|
||||
amount = bsqFormatter.formatCoin(Coin.valueOf(myBondedReputation.getAmount()));
|
||||
lockupDate = new Date(myBondedReputation.getLockupDate());
|
||||
lockupDateString = bsqFormatter.formatDateTime(lockupDate);
|
||||
lockTime = Integer.toString(myBondedReputation.getLockTime());
|
||||
lockupTxId = myBondedReputation.getLockupTxId();
|
||||
bondState = myBondedReputation.getBondState();
|
||||
bondStateString = Res.get("dao.bond.bondState." + myBondedReputation.getBondState().name());
|
||||
showButton = myBondedReputation.getBondState() == BondState.LOCKUP_TX_CONFIRMED;
|
||||
buttonText = Res.get("dao.bond.table.button.unlock");
|
||||
}
|
||||
}
|
|
@ -21,15 +21,13 @@
|
|||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.bonding.reputation.MyBondedReputationView"
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.bonding.reputation.MyReputationView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
||||
xmlns:fx="http://javafx.com/fxml">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
<ColumnConstraints minWidth="10" maxWidth="5"/>
|
||||
<ColumnConstraints percentWidth="50"/>
|
||||
<ColumnConstraints percentWidth="100"/>
|
||||
</columnConstraints>
|
||||
</GridPane>
|
||||
|
|
@ -19,10 +19,10 @@ package bisq.desktop.main.dao.bonding.reputation;
|
|||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
@ -33,8 +33,8 @@ import bisq.core.btc.listeners.BsqBalanceListener;
|
|||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.BondConsensus;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.reputation.MyBondedReputation;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
@ -45,7 +45,6 @@ import bisq.common.crypto.Hash;
|
|||
import bisq.common.util.Utilities;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -54,15 +53,11 @@ import com.google.common.base.Charsets;
|
|||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
import javafx.scene.layout.VBox;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
@ -75,7 +70,6 @@ import javafx.collections.transformation.SortedList;
|
|||
import javafx.util.Callback;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -84,26 +78,29 @@ import static bisq.desktop.util.FormBuilder.addInputTextField;
|
|||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
@FxmlView
|
||||
public class MyBondedReputationView extends ActivatableView<GridPane, Void> implements DaoStateListener, BsqBalanceListener {
|
||||
private final BsqWalletService bsqWalletService;
|
||||
public class MyReputationView extends ActivatableView<GridPane, Void> implements BsqBalanceListener {
|
||||
private InputTextField amountInputTextField, timeInputTextField, saltInputTextField;
|
||||
private Button lockupButton;
|
||||
private TableView<MyReputationListItem> tableView;
|
||||
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final HexStringValidator hexStringValidator;
|
||||
private final BsqValidator bsqValidator;
|
||||
private final DaoFacade daoFacade;
|
||||
private final Preferences preferences;
|
||||
|
||||
private final IntegerValidator timeInputTextFieldValidator;
|
||||
|
||||
private final ObservableList<MyReputationListItem> observableList = FXCollections.observableArrayList();
|
||||
private final SortedList<MyReputationListItem> sortedList = new SortedList<>(observableList);
|
||||
|
||||
private int gridRow = 0;
|
||||
private InputTextField amountInputTextField, timeInputTextField, saltInputTextField;
|
||||
private Button lockupButton;
|
||||
private TableView<MyBondedReputationListItem> tableView;
|
||||
|
||||
private ChangeListener<Boolean> amountFocusOutListener, timeFocusOutListener, saltFocusOutListener;
|
||||
private ChangeListener<String> amountInputTextFieldListener, timeInputTextFieldListener, saltInputTextFieldListener;
|
||||
private final ObservableList<MyBondedReputationListItem> observableList = FXCollections.observableArrayList();
|
||||
private final SortedList<MyBondedReputationListItem> sortedList = new SortedList<>(observableList);
|
||||
private ListChangeListener<Transaction> walletBsqTransactionsListener;
|
||||
private ChangeListener<Number> walletChainHeightListener;
|
||||
private ListChangeListener<MyBondedReputation> myBondedReputationsChangeListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -111,15 +108,15 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private MyBondedReputationView(BsqWalletService bsqWalletService,
|
||||
BsqFormatter bsqFormatter,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
HexStringValidator hexStringValidator,
|
||||
BsqValidator bsqValidator,
|
||||
DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
private MyReputationView(BsqFormatter bsqFormatter,
|
||||
BsqWalletService bsqWalletService,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
HexStringValidator hexStringValidator,
|
||||
BsqValidator bsqValidator,
|
||||
DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.hexStringValidator = hexStringValidator;
|
||||
this.bsqValidator = bsqValidator;
|
||||
|
@ -133,26 +130,23 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
|
||||
@Override
|
||||
public void initialize() {
|
||||
int columnSpan = 3;
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, gridRow, 3, Res.get("dao.bonding.reputation.header"));
|
||||
GridPane.setColumnSpan(titledGroupBg, columnSpan);
|
||||
addTitledGroupBg(root, gridRow, 3, Res.get("dao.bonding.reputation.header"));
|
||||
|
||||
amountInputTextField = addInputTextField(root, gridRow, Res.get("dao.bonding.lock.amount"),
|
||||
Layout.FIRST_ROW_DISTANCE);
|
||||
amountInputTextField.setValidator(bsqValidator);
|
||||
GridPane.setColumnSpan(amountInputTextField, columnSpan);
|
||||
|
||||
timeInputTextField = FormBuilder.addInputTextField(root, ++gridRow, Res.get("dao.bonding.lock.time"));
|
||||
GridPane.setColumnSpan(timeInputTextField, columnSpan);
|
||||
timeInputTextField.setValidator(timeInputTextFieldValidator);
|
||||
|
||||
saltInputTextField = FormBuilder.addInputTextField(root, ++gridRow, Res.get("dao.bonding.lock.salt"));
|
||||
GridPane.setColumnSpan(saltInputTextField, columnSpan);
|
||||
saltInputTextField.setValidator(hexStringValidator);
|
||||
|
||||
lockupButton = addButtonAfterGroup(root, ++gridRow, Res.get("dao.bonding.lock.lockupButton"));
|
||||
|
||||
createTableView(columnSpan);
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, ++gridRow, Res.get("dao.bonding.reputation.list.header"), 20);
|
||||
createColumns();
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
createListeners();
|
||||
}
|
||||
|
@ -168,9 +162,10 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
saltInputTextField.textProperty().addListener(saltInputTextFieldListener);
|
||||
saltInputTextField.focusedProperty().addListener(saltFocusOutListener);
|
||||
|
||||
bsqWalletService.getWalletTransactions().addListener(walletBsqTransactionsListener);
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
|
||||
daoFacade.getMyBondedReputations().addListener(myBondedReputationsChangeListener);
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
bsqWalletService.getChainHeightProperty().addListener(walletChainHeightListener);
|
||||
|
||||
lockupButton.setOnAction((event) -> {
|
||||
Coin lockupAmount = bsqFormatter.parseToCoin(amountInputTextField.getText());
|
||||
|
@ -186,23 +181,18 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
setNewRandomSalt();
|
||||
});
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
amountInputTextField.resetValidation();
|
||||
timeInputTextField.resetValidation();
|
||||
|
||||
//TODO maybe show generate salt button instead
|
||||
setNewRandomSalt();
|
||||
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
onUpdateBalances();
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
observableList.forEach(MyBondedReputationListItem::cleanup);
|
||||
|
||||
amountInputTextField.textProperty().removeListener(amountInputTextFieldListener);
|
||||
amountInputTextField.focusedProperty().removeListener(amountFocusOutListener);
|
||||
|
||||
|
@ -212,36 +202,14 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
saltInputTextField.textProperty().removeListener(saltInputTextFieldListener);
|
||||
saltInputTextField.focusedProperty().removeListener(saltFocusOutListener);
|
||||
|
||||
bsqWalletService.getWalletTransactions().removeListener(walletBsqTransactionsListener);
|
||||
bsqWalletService.addBsqBalanceListener(this);
|
||||
bsqWalletService.getChainHeightProperty().removeListener(walletChainHeightListener);
|
||||
|
||||
lockupButton.setOnAction(null);
|
||||
daoFacade.getMyBondedReputations().removeListener(myBondedReputationsChangeListener);
|
||||
bsqWalletService.removeBsqBalanceListener(this);
|
||||
|
||||
sortedList.comparatorProperty().unbind();
|
||||
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
lockupButton.setOnAction(null);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BsqBalanceListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -254,7 +222,6 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
Coin lockupBondsBalance,
|
||||
Coin unlockingBondsBalance) {
|
||||
bsqValidator.setAvailableBalance(confirmedBalance);
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
|
||||
|
@ -266,19 +233,16 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
amountFocusOutListener = (observable, oldValue, newValue) -> {
|
||||
if (!newValue) {
|
||||
updateButtonState();
|
||||
onUpdateBalances();
|
||||
}
|
||||
};
|
||||
timeFocusOutListener = (observable, oldValue, newValue) -> {
|
||||
if (!newValue) {
|
||||
updateButtonState();
|
||||
onUpdateBalances();
|
||||
}
|
||||
};
|
||||
saltFocusOutListener = (observable, oldValue, newValue) -> {
|
||||
if (!newValue) {
|
||||
updateButtonState();
|
||||
onUpdateBalances();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -286,26 +250,15 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
timeInputTextFieldListener = (observable, oldValue, newValue) -> updateButtonState();
|
||||
saltInputTextFieldListener = (observable, oldValue, newValue) -> updateButtonState();
|
||||
|
||||
walletBsqTransactionsListener = change -> updateList();
|
||||
walletChainHeightListener = (observable, oldValue, newValue) -> updateList();
|
||||
myBondedReputationsChangeListener = c -> updateList();
|
||||
}
|
||||
|
||||
private void createTableView(int columnSpan) {
|
||||
TitledGroupBg titledGroupBg2 = addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.bonding.reputation.list.header"), 20);
|
||||
GridPane.setColumnSpan(titledGroupBg2, columnSpan);
|
||||
|
||||
tableView = new TableView<>();
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
createColumns();
|
||||
|
||||
VBox vBox = new VBox();
|
||||
vBox.setSpacing(10);
|
||||
GridPane.setRowIndex(vBox, ++gridRow);
|
||||
GridPane.setColumnSpan(vBox, columnSpan);
|
||||
GridPane.setMargin(vBox, new Insets(50, -10, 5, -10));
|
||||
vBox.getChildren().addAll(tableView);
|
||||
root.getChildren().add(vBox);
|
||||
private void updateList() {
|
||||
observableList.setAll(daoFacade.getMyBondedReputations().stream()
|
||||
.map(myBondedReputation -> new MyReputationListItem(myBondedReputation, bsqFormatter))
|
||||
.sorted(Comparator.comparing(MyReputationListItem::getLockupDateString).reversed())
|
||||
.collect(Collectors.toList()));
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 41, 28, 2, 30);
|
||||
}
|
||||
|
||||
private void setNewRandomSalt() {
|
||||
|
@ -315,15 +268,6 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
saltInputTextField.resetValidation();
|
||||
}
|
||||
|
||||
private void onUpdateBalances() {
|
||||
onUpdateBalances(bsqWalletService.getAvailableBalance(),
|
||||
bsqWalletService.getAvailableNonBsqBalance(),
|
||||
bsqWalletService.getUnverifiedBalance(),
|
||||
bsqWalletService.getLockedForVotingBalance(),
|
||||
bsqWalletService.getLockupBondsBalance(),
|
||||
bsqWalletService.getUnlockingBondsBalance());
|
||||
}
|
||||
|
||||
private void updateButtonState() {
|
||||
boolean isValid = bsqValidator.validate(amountInputTextField.getText()).isValid &&
|
||||
timeInputTextFieldValidator.validate(timeInputTextField.getText()).isValid &&
|
||||
|
@ -331,29 +275,13 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
lockupButton.setDisable(!isValid);
|
||||
}
|
||||
|
||||
private void openTxInBlockExplorer(MyBondedReputationListItem item) {
|
||||
if (item.getTxId() != null)
|
||||
GUIUtil.openWebPage(preferences.getBsqBlockChainExplorer().txUrl + item.getTxId());
|
||||
}
|
||||
|
||||
private void updateList() {
|
||||
List<MyBondedReputationListItem> items = daoFacade.getMyBondedReputations().stream()
|
||||
.map(myBondedReputation -> {
|
||||
return new MyBondedReputationListItem(myBondedReputation, daoFacade, bondingViewUtils, bsqFormatter);
|
||||
})
|
||||
.sorted(Comparator.comparing(MyBondedReputationListItem::getLockupDate).reversed())
|
||||
.collect(Collectors.toList());
|
||||
observableList.setAll(items);
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 41, 28, 2, 10);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Table columns
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createColumns() {
|
||||
TableColumn<MyBondedReputationListItem, MyBondedReputationListItem> column;
|
||||
TableColumn<MyReputationListItem, MyReputationListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("shared.amountWithCur", "BSQ"));
|
||||
column.setMinWidth(120);
|
||||
|
@ -361,11 +289,11 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getAmount());
|
||||
|
@ -383,11 +311,11 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getLockTime());
|
||||
|
@ -405,25 +333,16 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
Label label;
|
||||
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (label == null) {
|
||||
label = item.getStateLabel();
|
||||
setGraphic(label);
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (label != null)
|
||||
label = null;
|
||||
}
|
||||
setText(item.getBondStateString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -436,15 +355,15 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getLockupDate());
|
||||
setText(item.getLockupDateString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
|
@ -459,19 +378,19 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
//noinspection Duplicates
|
||||
if (item != null && !empty) {
|
||||
String transactionId = item.getTxId();
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(transactionId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(item));
|
||||
hyperlinkWithIcon.setOnAction(event -> GUIUtil.openTxInBsqBlockExplorer(item.getTxId(), preferences));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", transactionId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
|
@ -490,11 +409,11 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getSalt());
|
||||
|
@ -511,11 +430,11 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getHash());
|
||||
|
@ -533,23 +452,30 @@ public class MyBondedReputationView extends ActivatableView<GridPane, Void> impl
|
|||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<MyBondedReputationListItem, MyBondedReputationListItem> call(TableColumn<MyBondedReputationListItem,
|
||||
MyBondedReputationListItem> column) {
|
||||
public TableCell<MyReputationListItem, MyReputationListItem> call(TableColumn<MyReputationListItem,
|
||||
MyReputationListItem> column) {
|
||||
return new TableCell<>() {
|
||||
Button button;
|
||||
AutoTooltipButton button;
|
||||
|
||||
@Override
|
||||
public void updateItem(final MyBondedReputationListItem item, boolean empty) {
|
||||
public void updateItem(final MyReputationListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
if (button == null) {
|
||||
button = item.getButton();
|
||||
setGraphic(button);
|
||||
}
|
||||
if (item != null && !empty && item.isShowButton()) {
|
||||
button = new AutoTooltipButton(item.getButtonText());
|
||||
button.setOnAction(e -> {
|
||||
if (item.getBondState() == BondState.LOCKUP_TX_CONFIRMED) {
|
||||
bondingViewUtils.unLock(item.getLockupTxId(),
|
||||
txId -> {
|
||||
});
|
||||
}
|
||||
});
|
||||
setGraphic(button);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (button != null)
|
||||
if (button != null) {
|
||||
button.setOnAction(null);
|
||||
button = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,145 +0,0 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.bonding.roles;
|
||||
|
||||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.state.model.governance.Role;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@EqualsAndHashCode
|
||||
class BondedRolesListItem implements DaoStateListener {
|
||||
@Getter
|
||||
private final BondedRole bondedRole;
|
||||
private final DaoFacade daoFacade;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
@Getter
|
||||
private final AutoTooltipButton button;
|
||||
@Getter
|
||||
private final Label label;
|
||||
@Getter
|
||||
private final Role role;
|
||||
|
||||
private final boolean isMyRole;
|
||||
|
||||
BondedRolesListItem(BondedRole bondedRole,
|
||||
DaoFacade daoFacade,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
BsqFormatter bsqFormatter) {
|
||||
this.bondedRole = bondedRole;
|
||||
this.daoFacade = daoFacade;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
|
||||
role = bondedRole.getBondedAsset();
|
||||
isMyRole = daoFacade.isMyRole(role);
|
||||
|
||||
daoFacade.addBsqStateListener(this);
|
||||
|
||||
button = new AutoTooltipButton();
|
||||
button.setMinWidth(70);
|
||||
label = new Label();
|
||||
|
||||
button.setOnAction(e -> {
|
||||
if (bondedRole.getBondState() == BondState.READY_FOR_LOCKUP) {
|
||||
bondingViewUtils.lockupBondForBondedRole(role,
|
||||
txId -> {
|
||||
/*bondedRole.setLockupTxId(txId);
|
||||
bondedRole.setBondState(BondState.LOCKUP_TX_PENDING);
|
||||
update();
|
||||
button.setDisable(true);*/
|
||||
});
|
||||
} else if (bondedRole.getBondState() == BondState.LOCKUP_TX_CONFIRMED) {
|
||||
bondingViewUtils.unLock(bondedRole.getLockupTxId(),
|
||||
txId -> {
|
||||
/*bondedRole.setUnlockTxId(txId);
|
||||
bondedRole.setBondState(BondState.UNLOCK_TX_PENDING);
|
||||
update();
|
||||
button.setDisable(true);*/
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
public String getStartDate() {
|
||||
return bondedRole.getLockupDate() > 0 ?
|
||||
bsqFormatter.formatDateTime(new Date(bondedRole.getLockupDate())) :
|
||||
"-";
|
||||
}
|
||||
|
||||
public String getRevokeDate() {
|
||||
return bondedRole.getUnlockDate() > 0 ?
|
||||
bsqFormatter.formatDateTime(new Date(bondedRole.getUnlockDate())) :
|
||||
"-";
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
button.setOnAction(null);
|
||||
}
|
||||
|
||||
|
||||
private void update() {
|
||||
label.setText(Res.get("dao.bond.bondState." + bondedRole.getBondState().name()));
|
||||
|
||||
boolean showLockup = bondedRole.getBondState() == BondState.READY_FOR_LOCKUP;
|
||||
boolean showRevoke = bondedRole.getBondState() == BondState.LOCKUP_TX_CONFIRMED;
|
||||
if (showLockup)
|
||||
button.updateText(Res.get("dao.bond.table.button.lockup"));
|
||||
else if (showRevoke)
|
||||
button.updateText(Res.get("dao.bond.table.button.revoke"));
|
||||
|
||||
|
||||
boolean showButton = isMyRole && (showLockup || showRevoke);
|
||||
button.setVisible(showButton);
|
||||
button.setManaged(showButton);
|
||||
}
|
||||
|
||||
// DaoStateListener
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
}
|
||||
}
|
|
@ -30,19 +30,19 @@ import javafx.geometry.Insets;
|
|||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
//TODO not used atm but keep it as is should be used
|
||||
@Slf4j
|
||||
class BondedRoleTypeWindow extends Overlay<BondedRoleTypeWindow> {
|
||||
class RoleDetailsWindow extends Overlay<RoleDetailsWindow> {
|
||||
private final BondedRoleType bondedRoleType;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
|
||||
|
||||
public BondedRoleTypeWindow(BondedRoleType bondedRoleType, BsqFormatter bsqFormatter) {
|
||||
public RoleDetailsWindow(BondedRoleType bondedRoleType, BsqFormatter bsqFormatter) {
|
||||
this.bondedRoleType = bondedRoleType;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
|
||||
width = 968;
|
||||
type = Type.Confirmation;
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* This file is part of Bisq.
|
||||
*
|
||||
* Bisq 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.
|
||||
*
|
||||
* Bisq 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 Bisq. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package bisq.desktop.main.dao.bonding.roles;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.state.model.governance.Role;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import lombok.Value;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
@Value
|
||||
class RolesListItem {
|
||||
private final BondedRole bondedRole;
|
||||
private final Role role;
|
||||
private final String buttonText;
|
||||
private final boolean isButtonVisible;
|
||||
private final BondState bondState;
|
||||
private final String bondStateString;
|
||||
private final String lockupTxId;
|
||||
private final Date lockupDate;
|
||||
|
||||
RolesListItem(BondedRole bondedRole,
|
||||
DaoFacade daoFacade) {
|
||||
this.bondedRole = bondedRole;
|
||||
|
||||
role = bondedRole.getBondedAsset();
|
||||
boolean isMyRole = daoFacade.isMyRole(role);
|
||||
bondState = bondedRole.getBondState();
|
||||
lockupTxId = bondedRole.getLockupTxId();
|
||||
lockupDate = new Date(bondedRole.getLockupDate());
|
||||
bondStateString = Res.get("dao.bond.bondState." + bondedRole.getBondState().name());
|
||||
|
||||
boolean showLockup = bondedRole.getBondState() == BondState.READY_FOR_LOCKUP;
|
||||
boolean showRevoke = bondedRole.getBondState() == BondState.LOCKUP_TX_CONFIRMED;
|
||||
if (showLockup) {
|
||||
buttonText = Res.get("dao.bond.table.button.lockup");
|
||||
} else if (showRevoke) {
|
||||
buttonText = Res.get("dao.bond.table.button.revoke");
|
||||
} else {
|
||||
buttonText = "";
|
||||
}
|
||||
|
||||
isButtonVisible = isMyRole && (showLockup || showRevoke);
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@
|
|||
<?import javafx.scene.layout.AnchorPane?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.bonding.roles.BondedRolesView"
|
||||
<GridPane fx:id="root" fx:controller="bisq.desktop.main.dao.bonding.roles.RolesView"
|
||||
hgap="5.0" vgap="5.0"
|
||||
AnchorPane.bottomAnchor="20.0" AnchorPane.leftAnchor="20.0"
|
||||
AnchorPane.rightAnchor="25.0" AnchorPane.topAnchor="20.0"
|
|
@ -19,15 +19,16 @@ package bisq.desktop.main.dao.bonding.roles;
|
|||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.dao.bonding.BondingViewUtils;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.state.DaoStateListener;
|
||||
import bisq.core.dao.state.model.blockchain.Block;
|
||||
import bisq.core.dao.governance.bond.BondState;
|
||||
import bisq.core.dao.governance.bond.role.BondedRole;
|
||||
import bisq.core.dao.state.model.governance.BondedRoleType;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.user.Preferences;
|
||||
|
@ -37,7 +38,6 @@ import javax.inject.Inject;
|
|||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Hyperlink;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableCell;
|
||||
|
@ -46,31 +46,31 @@ import javafx.scene.control.TableView;
|
|||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.property.ReadOnlyObjectWrapper;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
@FxmlView
|
||||
public class BondedRolesView extends ActivatableView<GridPane, Void> implements DaoStateListener {
|
||||
private TableView<BondedRolesListItem> tableView;
|
||||
public class RolesView extends ActivatableView<GridPane, Void> {
|
||||
private TableView<RolesListItem> tableView;
|
||||
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BondingViewUtils bondingViewUtils;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final DaoFacade daoFacade;
|
||||
private final Preferences preferences;
|
||||
|
||||
private final ObservableList<BondedRolesListItem> observableList = FXCollections.observableArrayList();
|
||||
private final SortedList<BondedRolesListItem> sortedList = new SortedList<>(observableList);
|
||||
private final ObservableList<RolesListItem> observableList = FXCollections.observableArrayList();
|
||||
private final SortedList<RolesListItem> sortedList = new SortedList<>(observableList);
|
||||
|
||||
private ListChangeListener<BondedRole> bondedRoleListChangeListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -78,10 +78,10 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Inject
|
||||
private BondedRolesView(BsqFormatter bsqFormatter,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
private RolesView(BsqFormatter bsqFormatter,
|
||||
BondingViewUtils bondingViewUtils,
|
||||
DaoFacade daoFacade,
|
||||
Preferences preferences) {
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.bondingViewUtils = bondingViewUtils;
|
||||
this.daoFacade = daoFacade;
|
||||
|
@ -91,50 +91,24 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
@Override
|
||||
public void initialize() {
|
||||
int gridRow = 0;
|
||||
addTitledGroupBg(root, gridRow, 2, Res.get("dao.bond.bondedRoles"));
|
||||
|
||||
tableView = new TableView<>();
|
||||
GridPane.setRowIndex(tableView, ++gridRow);
|
||||
GridPane.setMargin(tableView, new Insets(30, -10, 5, -10));
|
||||
root.getChildren().add(tableView);
|
||||
tableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tableView = FormBuilder.addTableViewWithHeader(root, gridRow, Res.get("dao.bond.bondedRoles"));
|
||||
createColumns();
|
||||
tableView.setItems(sortedList);
|
||||
|
||||
bondedRoleListChangeListener = c -> updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void activate() {
|
||||
daoFacade.addBsqStateListener(this);
|
||||
sortedList.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
|
||||
daoFacade.getBondedRoles().addListener(bondedRoleListChangeListener);
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
sortedList.comparatorProperty().unbind();
|
||||
|
||||
observableList.forEach(BondedRolesListItem::cleanup);
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// DaoStateListener
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onNewBlockHeight(int blockHeight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseTxsComplete(Block block) {
|
||||
updateList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onParseBlockChainComplete() {
|
||||
daoFacade.getBondedRoles().removeListener(bondedRoleListChangeListener);
|
||||
}
|
||||
|
||||
|
||||
|
@ -142,17 +116,12 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
// Private
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
private void updateList() {
|
||||
observableList.forEach(BondedRolesListItem::cleanup);
|
||||
observableList.setAll(daoFacade.getBondedRoles().stream()
|
||||
.map(bond -> new BondedRolesListItem(bond, daoFacade, bondingViewUtils, bsqFormatter))
|
||||
.map(bond -> new RolesListItem(bond, daoFacade))
|
||||
.sorted(Comparator.comparing(RolesListItem::getLockupDate).reversed())
|
||||
.collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
private void openTxInBlockExplorer(String transactionId) {
|
||||
if (transactionId != null)
|
||||
GUIUtil.openWebPage(preferences.getBsqBlockChainExplorer().txUrl + transactionId);
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 41, 28, 2, 30);
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,20 +130,19 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private void createColumns() {
|
||||
TableColumn<BondedRolesListItem, BondedRolesListItem> column;
|
||||
TableColumn<RolesListItem, RolesListItem> column;
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.name"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(80);
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getRole().getName());
|
||||
|
@ -191,15 +159,14 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
column.setMinWidth(60);
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
String link = item.getRole().getLink();
|
||||
|
@ -223,15 +190,14 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
column.setMinWidth(80);
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private Hyperlink hyperlink;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
|
@ -239,7 +205,7 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
String type = bondedRoleType.getDisplayString();
|
||||
hyperlink = new Hyperlink(type);
|
||||
hyperlink.setOnAction(event -> {
|
||||
new BondedRoleTypeWindow(bondedRoleType, bsqFormatter).show();
|
||||
new RoleDetailsWindow(bondedRoleType, bsqFormatter).show();
|
||||
});
|
||||
hyperlink.setTooltip(new Tooltip(Res.get("tooltip.openPopupForDetails", type)));
|
||||
setGraphic(hyperlink);
|
||||
|
@ -254,77 +220,27 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
});
|
||||
tableView.getColumns().add(column);
|
||||
|
||||
/* column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.startDate"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(120);
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<BondedRolesListItem, BondedRolesListItem>, TableCell<BondedRolesListItem,
|
||||
BondedRolesListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
return new TableCell<BondedRolesListItem, BondedRolesListItem>() {
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getStartDate());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
tableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.revokeDate"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(120);
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<BondedRolesListItem, BondedRolesListItem>, TableCell<BondedRolesListItem,
|
||||
BondedRolesListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
return new TableCell<BondedRolesListItem, BondedRolesListItem>() {
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
if (item != null && !empty) {
|
||||
setText(item.getRevokeDate());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
tableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.lockupTxId"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(80);
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<BondedRolesListItem, BondedRolesListItem>, TableCell<BondedRolesListItem,
|
||||
BondedRolesListItem>>() {
|
||||
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
return new TableCell<BondedRolesListItem, BondedRolesListItem>() {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
private Label label;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
String transactionId = item.getBondedRole().getLockupTxId();
|
||||
if (transactionId != null) {
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(transactionId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(transactionId));
|
||||
hyperlinkWithIcon.setOnAction(event -> GUIUtil.openTxInBsqBlockExplorer(transactionId, preferences));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", transactionId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
|
@ -344,73 +260,22 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
});
|
||||
tableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.unlockTxId"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(80);
|
||||
column.setCellFactory(
|
||||
new Callback<TableColumn<BondedRolesListItem, BondedRolesListItem>, TableCell<BondedRolesListItem,
|
||||
BondedRolesListItem>>() {
|
||||
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
return new TableCell<BondedRolesListItem, BondedRolesListItem>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
private Label label;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
String transactionId = item.getBondedRole().getUnlockTxId();
|
||||
if (transactionId != null) {
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(transactionId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(transactionId));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", transactionId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
label = new Label("-");
|
||||
setGraphic(label);
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (hyperlinkWithIcon != null)
|
||||
hyperlinkWithIcon.setOnAction(null);
|
||||
if (label != null)
|
||||
label = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
tableView.getColumns().add(column);*/
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.bond.table.column.header.bondState"));
|
||||
column.setCellValueFactory(item -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setMinWidth(120);
|
||||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
Label label;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (label == null) {
|
||||
label = item.getLabel();
|
||||
setGraphic(label);
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (label != null)
|
||||
label = null;
|
||||
}
|
||||
setText(item.getBondStateString());
|
||||
} else
|
||||
setText("");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -423,24 +288,37 @@ public class BondedRolesView extends ActivatableView<GridPane, Void> implements
|
|||
column.setCellFactory(
|
||||
new Callback<>() {
|
||||
@Override
|
||||
public TableCell<BondedRolesListItem, BondedRolesListItem> call(TableColumn<BondedRolesListItem,
|
||||
BondedRolesListItem> column) {
|
||||
public TableCell<RolesListItem, RolesListItem> call(TableColumn<RolesListItem,
|
||||
RolesListItem> column) {
|
||||
return new TableCell<>() {
|
||||
Button button;
|
||||
AutoTooltipButton button;
|
||||
|
||||
@Override
|
||||
public void updateItem(final BondedRolesListItem item, boolean empty) {
|
||||
public void updateItem(final RolesListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (item != null && !empty && item.isButtonVisible()) {
|
||||
if (button == null) {
|
||||
button = item.getButton();
|
||||
button = new AutoTooltipButton(item.getButtonText());
|
||||
button.setMinWidth(70);
|
||||
button.setOnAction(e -> {
|
||||
if (item.getBondState() == BondState.READY_FOR_LOCKUP) {
|
||||
bondingViewUtils.lockupBondForBondedRole(item.getRole(),
|
||||
txId -> {
|
||||
});
|
||||
} else if (item.getBondState() == BondState.LOCKUP_TX_CONFIRMED) {
|
||||
bondingViewUtils.unLock(item.getLockupTxId(),
|
||||
txId -> {
|
||||
});
|
||||
}
|
||||
});
|
||||
setGraphic(button);
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (button != null)
|
||||
if (button != null) {
|
||||
button.setOnAction(null);
|
||||
button = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
|
@ -216,9 +216,13 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
|||
Coin miningFee = transaction.getFee();
|
||||
int txSize = transaction.bitcoinSerialize().length;
|
||||
Coin fee = daoFacade.getProposalFee(daoFacade.getChainHeight());
|
||||
GUIUtil.showBsqFeeInfoPopup(fee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.proposal"), () -> doPublishMyProposal(proposal, transaction));
|
||||
|
||||
if (!DevEnv.isDevMode()) {
|
||||
GUIUtil.showBsqFeeInfoPopup(fee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.proposal"), () -> doPublishMyProposal(proposal, transaction));
|
||||
} else {
|
||||
doPublishMyProposal(proposal, transaction);
|
||||
}
|
||||
} catch (InsufficientMoneyException e) {
|
||||
BSFormatter formatter = e instanceof InsufficientBsqException ? bsqFormatter : btcFormatter;
|
||||
new Popup<>().warning(Res.get("dao.proposal.create.missingFunds",
|
||||
|
|
|
@ -495,8 +495,12 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
Coin miningFee = miningFeeAndTxSize.first;
|
||||
int txSize = miningFeeAndTxSize.second;
|
||||
Coin blindVoteFee = daoFacade.getBlindVoteFeeForCycle();
|
||||
GUIUtil.showBsqFeeInfoPopup(blindVoteFee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.blindVote"), () -> publishBlindVote(stake));
|
||||
if (!DevEnv.isDevMode()) {
|
||||
GUIUtil.showBsqFeeInfoPopup(blindVoteFee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.blindVote"), () -> publishBlindVote(stake));
|
||||
} else {
|
||||
publishBlindVote(stake);
|
||||
}
|
||||
} catch (InsufficientMoneyException | WalletException | TransactionVerificationException exception) {
|
||||
new Popup<>().warning(exception.toString()).show();
|
||||
}
|
||||
|
|
|
@ -64,6 +64,7 @@ import javafx.scene.control.DatePicker;
|
|||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.ListView;
|
||||
import javafx.scene.control.RadioButton;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.TextArea;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.ToggleButton;
|
||||
|
@ -1680,4 +1681,19 @@ public class FormBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText) {
|
||||
return addTableViewWithHeader(gridPane, rowIndex, headerText, 0);
|
||||
}
|
||||
|
||||
public static <T> TableView<T> addTableViewWithHeader(GridPane gridPane, int rowIndex, String headerText, int top) {
|
||||
addTitledGroupBg(gridPane, rowIndex, 1, headerText, top);
|
||||
|
||||
TableView<T> tableView = new TableView<>();
|
||||
GridPane.setRowIndex(tableView, rowIndex);
|
||||
GridPane.setMargin(tableView, new Insets(top + 30, -10, 5, -10));
|
||||
gridPane.getChildren().add(tableView);
|
||||
tableView.setPlaceholder(new AutoTooltipLabel(Res.get("table.placeholder.noData")));
|
||||
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
return tableView;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -904,4 +904,9 @@ public class GUIUtil {
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static void openTxInBsqBlockExplorer(String txId, Preferences preferences) {
|
||||
if (txId != null)
|
||||
GUIUtil.openWebPage(preferences.getBsqBlockChainExplorer().txUrl + txId);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue