mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-22 22:45:21 +01:00
Merge pull request #1795 from ManfredKarrer/DAO-UI-hide-details
Dao UI improvements
This commit is contained in:
commit
fd6681b9a9
51 changed files with 715 additions and 358 deletions
|
@ -917,6 +917,7 @@ message PersistableEnvelope {
|
|||
UserPayload user_payload = 10;
|
||||
PaymentAccountList payment_account_list = 11;
|
||||
|
||||
// deprecated
|
||||
// BsqState bsq_state = 12; // not used but as other non-dao data have a higher index number we leave it to make clear that we cannot change following indexes
|
||||
|
||||
AccountAgeWitnessStore account_age_witness_store = 13;
|
||||
|
@ -1272,6 +1273,9 @@ message PreferencesPayload {
|
|||
bool use_market_notifications = 43;
|
||||
bool use_price_notifications = 44;
|
||||
bool use_standby_mode = 45;
|
||||
bool is_dao_full_node = 46;
|
||||
string rpc_user = 47;
|
||||
string rpc_pw = 48;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -430,9 +430,8 @@ public abstract class BisqExecutable implements GracefulShutDownHandler {
|
|||
parser.accepts(DaoOptionKeys.FULL_DAO_NODE,
|
||||
description("If set to true the node requests the blockchain data via RPC requests from Bitcoin Core and " +
|
||||
"provide the validated BSQ txs to the network. It requires that the other RPC properties are " +
|
||||
"set as well.", false))
|
||||
.withRequiredArg()
|
||||
.ofType(boolean.class);
|
||||
"set as well.", ""))
|
||||
.withRequiredArg();
|
||||
parser.accepts(DaoOptionKeys.GENESIS_TX_ID,
|
||||
description("Genesis transaction ID when not using the hard coded one", ""))
|
||||
.withRequiredArg();
|
||||
|
|
|
@ -641,4 +641,8 @@ public class BsqWalletService extends WalletService implements DaoStateListener
|
|||
.findAny()
|
||||
.orElse(wallet.freshReceiveAddress());
|
||||
}
|
||||
|
||||
public String getUnusedBsqAddressAsString() {
|
||||
return "B" + getUnusedAddress().toBase58();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,7 @@ import bisq.core.dao.state.blockchain.Tx;
|
|||
import bisq.core.dao.state.blockchain.TxOutput;
|
||||
import bisq.core.dao.state.blockchain.TxOutputKey;
|
||||
import bisq.core.dao.state.blockchain.TxType;
|
||||
import bisq.core.dao.state.governance.Issuance;
|
||||
import bisq.core.dao.state.governance.Param;
|
||||
import bisq.core.dao.state.period.DaoPhase;
|
||||
import bisq.core.dao.state.period.PeriodService;
|
||||
|
@ -80,6 +81,8 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
|
||||
|
@ -90,6 +93,7 @@ import bisq.asset.Asset;
|
|||
* Provides a facade to interact with the Dao domain. Hides complexity and domain details to clients (e.g. UI or APIs)
|
||||
* by providing a reduced API and/or aggregating subroutines.
|
||||
*/
|
||||
@Slf4j
|
||||
public class DaoFacade implements DaoSetupService {
|
||||
private final ProposalListPresentation proposalListPresentation;
|
||||
private final BallotListService ballotListService;
|
||||
|
@ -212,13 +216,11 @@ public class DaoFacade implements DaoSetupService {
|
|||
// Creation of Proposal and proposalTransaction
|
||||
public ProposalWithTransaction getCompensationProposalWithTransaction(String name,
|
||||
String link,
|
||||
Coin requestedBsq,
|
||||
String bsqAddress)
|
||||
Coin requestedBsq)
|
||||
throws ValidationException, InsufficientMoneyException, TxException {
|
||||
return compensationProposalService.createProposalWithTransaction(name,
|
||||
link,
|
||||
requestedBsq,
|
||||
bsqAddress);
|
||||
requestedBsq);
|
||||
}
|
||||
|
||||
public ProposalWithTransaction getParamProposalWithTransaction(String name,
|
||||
|
@ -358,16 +360,92 @@ public class DaoFacade implements DaoSetupService {
|
|||
// Use case: Presentation of phases
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public int getFirstBlockOfPhase(int height, DaoPhase.Phase phase) {
|
||||
return periodService.getFirstBlockOfPhase(height, phase);
|
||||
// Because last block in request and voting phases must not be used fo making a tx as it will get confirmed in the
|
||||
// next block which would be already the next phase we hide that last block to the user and add it to the break.
|
||||
public int getFirstBlockOfPhaseForDisplay(int height, DaoPhase.Phase phase) {
|
||||
int firstBlock = periodService.getFirstBlockOfPhase(height, phase);
|
||||
switch (phase) {
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case PROPOSAL:
|
||||
break;
|
||||
case BREAK1:
|
||||
firstBlock++;
|
||||
break;
|
||||
case BLIND_VOTE:
|
||||
break;
|
||||
case BREAK2:
|
||||
firstBlock++;
|
||||
break;
|
||||
case VOTE_REVEAL:
|
||||
break;
|
||||
case BREAK3:
|
||||
firstBlock++;
|
||||
break;
|
||||
case RESULT:
|
||||
break;
|
||||
}
|
||||
|
||||
return firstBlock;
|
||||
}
|
||||
|
||||
public int getLastBlockOfPhase(int height, DaoPhase.Phase phase) {
|
||||
return periodService.getLastBlockOfPhase(height, phase);
|
||||
// Because last block in request and voting phases must not be used fo making a tx as it will get confirmed in the
|
||||
// next block which would be already the next phase we hide that last block to the user and add it to the break.
|
||||
public int getLastBlockOfPhaseForDisplay(int height, DaoPhase.Phase phase) {
|
||||
int lastBlock = periodService.getLastBlockOfPhase(height, phase);
|
||||
switch (phase) {
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case PROPOSAL:
|
||||
lastBlock--;
|
||||
break;
|
||||
case BREAK1:
|
||||
break;
|
||||
case BLIND_VOTE:
|
||||
lastBlock--;
|
||||
break;
|
||||
case BREAK2:
|
||||
break;
|
||||
case VOTE_REVEAL:
|
||||
lastBlock--;
|
||||
break;
|
||||
case BREAK3:
|
||||
break;
|
||||
case RESULT:
|
||||
break;
|
||||
}
|
||||
return lastBlock;
|
||||
}
|
||||
|
||||
public int getDurationForPhase(DaoPhase.Phase phase) {
|
||||
return periodService.getDurationForPhase(phase, daoStateService.getChainHeight());
|
||||
// Because last block in request and voting phases must not be used fo making a tx as it will get confirmed in the
|
||||
// next block which would be already the next phase we hide that last block to the user and add it to the break.
|
||||
public int getDurationForPhaseForDisplay(DaoPhase.Phase phase) {
|
||||
int duration = periodService.getDurationForPhase(phase, daoStateService.getChainHeight());
|
||||
switch (phase) {
|
||||
case UNDEFINED:
|
||||
break;
|
||||
case PROPOSAL:
|
||||
duration--;
|
||||
break;
|
||||
case BREAK1:
|
||||
duration++;
|
||||
break;
|
||||
case BLIND_VOTE:
|
||||
duration--;
|
||||
break;
|
||||
case BREAK2:
|
||||
duration++;
|
||||
break;
|
||||
case VOTE_REVEAL:
|
||||
duration--;
|
||||
break;
|
||||
case BREAK3:
|
||||
duration++;
|
||||
break;
|
||||
case RESULT:
|
||||
break;
|
||||
}
|
||||
return duration;
|
||||
}
|
||||
|
||||
// listeners for phase change
|
||||
|
@ -439,6 +517,10 @@ public class DaoFacade implements DaoSetupService {
|
|||
return daoStateService.getGenesisTotalSupply();
|
||||
}
|
||||
|
||||
public Set<Issuance> getIssuanceSet() {
|
||||
return daoStateService.getIssuanceSet();
|
||||
}
|
||||
|
||||
public Set<Tx> getFeeTxs() {
|
||||
return daoStateService.getBurntFeeTxs();
|
||||
}
|
||||
|
|
|
@ -256,9 +256,8 @@ public class MyProposalListService implements PersistedDataHost, DaoStateListene
|
|||
}
|
||||
|
||||
private boolean canRemoveProposal(Proposal proposal, DaoStateService daoStateService, PeriodService periodService) {
|
||||
return daoStateService.getTx(proposal.getTxId())
|
||||
.filter(tx -> isTxInProposalPhaseAndCycle(tx, periodService, daoStateService))
|
||||
.isPresent();
|
||||
boolean inPhase = periodService.isInPhase(daoStateService.getChainHeight(), DaoPhase.Phase.PROPOSAL);
|
||||
return isMine(proposal) && inPhase;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -62,11 +62,10 @@ public class CompensationProposalService extends BaseProposalService<Compensatio
|
|||
|
||||
public ProposalWithTransaction createProposalWithTransaction(String name,
|
||||
String link,
|
||||
Coin requestedBsq,
|
||||
String bsqAddress)
|
||||
Coin requestedBsq)
|
||||
throws ValidationException, InsufficientMoneyException, TxException {
|
||||
this.requestedBsq = requestedBsq;
|
||||
this.bsqAddress = bsqAddress;
|
||||
this.bsqAddress = bsqWalletService.getUnusedBsqAddressAsString();
|
||||
|
||||
return super.createProposalWithTransaction(name, link);
|
||||
}
|
||||
|
|
|
@ -72,10 +72,18 @@ public class ChangeParamValidator extends ProposalValidator {
|
|||
break;
|
||||
case DEFAULT_TAKER_FEE_BSQ:
|
||||
break;
|
||||
case MIN_MAKER_FEE_BSQ:
|
||||
break;
|
||||
case MIN_TAKER_FEE_BSQ:
|
||||
break;
|
||||
case DEFAULT_MAKER_FEE_BTC:
|
||||
break;
|
||||
case DEFAULT_TAKER_FEE_BTC:
|
||||
break;
|
||||
case MIN_MAKER_FEE_BTC:
|
||||
break;
|
||||
case MIN_TAKER_FEE_BTC:
|
||||
break;
|
||||
|
||||
case PROPOSAL_FEE:
|
||||
break;
|
||||
|
|
|
@ -17,14 +17,12 @@
|
|||
|
||||
package bisq.core.dao.node;
|
||||
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.dao.node.full.FullNode;
|
||||
import bisq.core.dao.node.lite.LiteNode;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import javax.inject.Named;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
@ -39,7 +37,14 @@ public class BsqNodeProvider {
|
|||
@Inject
|
||||
public BsqNodeProvider(LiteNode bsqLiteNode,
|
||||
FullNode bsqFullNode,
|
||||
@Named(DaoOptionKeys.FULL_DAO_NODE) boolean fullDaoNode) {
|
||||
bsqNode = fullDaoNode ? bsqFullNode : bsqLiteNode;
|
||||
Preferences preferences) {
|
||||
|
||||
boolean rpcDataSet = preferences.getRpcUser() != null && !preferences.getRpcUser().isEmpty()
|
||||
&& preferences.getRpcPw() != null && !preferences.getRpcPw().isEmpty();
|
||||
boolean daoFullNode = preferences.isDaoFullNode();
|
||||
if (daoFullNode && !rpcDataSet)
|
||||
log.warn("daoFullNode is set but RPC user and pw are missing");
|
||||
|
||||
bsqNode = rpcDataSet && daoFullNode ? bsqFullNode : bsqLiteNode;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
|
||||
package bisq.core.dao.node.full;
|
||||
|
||||
import bisq.core.app.BisqEnvironment;
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.dao.state.blockchain.PubKeyScript;
|
||||
import bisq.core.dao.state.blockchain.RawBlock;
|
||||
import bisq.core.dao.state.blockchain.RawTx;
|
||||
import bisq.core.dao.state.blockchain.RawTxOutput;
|
||||
import bisq.core.dao.state.blockchain.TxInput;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.handlers.ResultHandler;
|
||||
|
@ -90,15 +92,23 @@ public class RpcService {
|
|||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
@Inject
|
||||
public RpcService(@Named(DaoOptionKeys.RPC_USER) String rpcUser,
|
||||
@Named(DaoOptionKeys.RPC_PASSWORD) String rpcPassword,
|
||||
public RpcService(Preferences preferences,
|
||||
@Named(DaoOptionKeys.RPC_PORT) String rpcPort,
|
||||
@Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) String rpcBlockPort,
|
||||
@Named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) boolean dumpBlockchainData) {
|
||||
this.rpcUser = rpcUser;
|
||||
this.rpcPassword = rpcPassword;
|
||||
this.rpcPort = rpcPort;
|
||||
this.rpcBlockPort = rpcBlockPort;
|
||||
this.rpcUser = preferences.getRpcUser();
|
||||
this.rpcPassword = preferences.getRpcPw();
|
||||
|
||||
// mainnet is 8332, testnet 18332, regtest 18443
|
||||
boolean isPortSet = rpcPort != null && !rpcPort.isEmpty();
|
||||
boolean isMainnet = BisqEnvironment.getBaseCurrencyNetwork().isMainnet();
|
||||
boolean isTestnet = BisqEnvironment.getBaseCurrencyNetwork().isTestnet();
|
||||
this.rpcPort = isPortSet ? rpcPort :
|
||||
isMainnet ? "8332" :
|
||||
isTestnet ? "18332" :
|
||||
"18443"; // regtest
|
||||
this.rpcBlockPort = rpcBlockPort != null && !rpcBlockPort.isEmpty() ? rpcBlockPort : "5125";
|
||||
|
||||
this.dumpBlockchainData = dumpBlockchainData;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,16 +105,21 @@ public enum Param {
|
|||
PHASE_RESULT(2);
|
||||
|
||||
// See: https://github.com/bisq-network/proposals/issues/46
|
||||
/*
|
||||
PHASE_UNDEFINED(0),
|
||||
PHASE_PROPOSAL(3600), // 24 days
|
||||
PHASE_BREAK1(150), // 1 day
|
||||
PHASE_BLIND_VOTE(600), // 4 days
|
||||
PHASE_BREAK2(10), // 10 blocks
|
||||
PHASE_VOTE_REVEAL(300), // 2 days
|
||||
PHASE_BREAK3(10), // 10 blocks
|
||||
PHASE_RESULT(10); // 10 block
|
||||
*/
|
||||
// The last block in the proposal and vote phases are not shown to the user as he cannot make a tx there as it would be
|
||||
// confirmed in the next block which would be the following break phase. To hide that complexity we show only the
|
||||
// blocks where the user can be active. To have still round numbers for the durations we add 1 block to those
|
||||
// phases and subtract 1 block from the following breaks.
|
||||
// So in the UI the user will see 3600 blocks and the last
|
||||
// block of the technical 3601 blocks is displayed as part of the break1 phase.
|
||||
/* PHASE_UNDEFINED(0),
|
||||
PHASE_PROPOSAL(3601), // 24 days
|
||||
PHASE_BREAK1(149), // 1 day
|
||||
PHASE_BLIND_VOTE(601), // 4 days
|
||||
PHASE_BREAK2(9), // 10 blocks
|
||||
PHASE_VOTE_REVEAL(301), // 2 days
|
||||
PHASE_BREAK3(9), // 10 blocks
|
||||
PHASE_RESULT(10); // 10 block*/
|
||||
|
||||
|
||||
@Getter
|
||||
private long defaultValue;
|
||||
|
|
|
@ -39,7 +39,8 @@ public class CoreNetworkCapabilities {
|
|||
supportedCapabilities.add(Capabilities.Capability.BLIND_VOTE.ordinal());
|
||||
supportedCapabilities.add(Capabilities.Capability.BSQ_BLOCK.ordinal());
|
||||
|
||||
if (bisqEnvironment.getProperty(DaoOptionKeys.FULL_DAO_NODE, Boolean.class, false))
|
||||
String isFullDaoNode = bisqEnvironment.getProperty(DaoOptionKeys.FULL_DAO_NODE, String.class, "");
|
||||
if (isFullDaoNode != null && !isFullDaoNode.isEmpty())
|
||||
supportedCapabilities.add(Capabilities.Capability.DAO_FULL_NODE.ordinal());
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ import bisq.core.btc.BaseCurrencyNetwork;
|
|||
import bisq.core.btc.BtcOptionKeys;
|
||||
import bisq.core.btc.nodes.BtcNodes;
|
||||
import bisq.core.btc.wallet.Restrictions;
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.locale.Country;
|
||||
import bisq.core.locale.CountryUtil;
|
||||
import bisq.core.locale.CryptoCurrency;
|
||||
|
@ -139,9 +140,8 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
|
||||
private final Storage<PreferencesPayload> storage;
|
||||
private final BisqEnvironment bisqEnvironment;
|
||||
private final String btcNodesFromOptions;
|
||||
private final String useTorFlagFromOptions;
|
||||
private final String referralIdFromOptions;
|
||||
private final String btcNodesFromOptions, useTorFlagFromOptions, referralIdFromOptions, fullDaoNodeFromOptions,
|
||||
rpcUserFromOptions, rpcPasswordFromOptions;
|
||||
@Getter
|
||||
private final BooleanProperty useStandbyModeProperty = new SimpleBooleanProperty(prefPayload.isUseStandbyMode());
|
||||
|
||||
|
@ -157,13 +157,20 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
BisqEnvironment bisqEnvironment,
|
||||
@Named(BtcOptionKeys.BTC_NODES) String btcNodesFromOptions,
|
||||
@Named(BtcOptionKeys.USE_TOR_FOR_BTC) String useTorFlagFromOptions,
|
||||
@Named(AppOptionKeys.REFERRAL_ID) String referralId) {
|
||||
@Named(AppOptionKeys.REFERRAL_ID) String referralId,
|
||||
@Named(DaoOptionKeys.FULL_DAO_NODE) String fullDaoNode,
|
||||
@Named(DaoOptionKeys.RPC_USER) String rpcUser,
|
||||
@Named(DaoOptionKeys.RPC_PASSWORD) String rpcPassword) {
|
||||
|
||||
|
||||
this.storage = storage;
|
||||
this.bisqEnvironment = bisqEnvironment;
|
||||
this.btcNodesFromOptions = btcNodesFromOptions;
|
||||
this.useTorFlagFromOptions = useTorFlagFromOptions;
|
||||
this.referralIdFromOptions = referralId;
|
||||
this.fullDaoNodeFromOptions = fullDaoNode;
|
||||
this.rpcUserFromOptions = rpcUser;
|
||||
this.rpcPasswordFromOptions = rpcPassword;
|
||||
|
||||
useAnimationsProperty.addListener((ov) -> {
|
||||
prefPayload.setUseAnimations(useAnimationsProperty.get());
|
||||
|
@ -206,7 +213,7 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
@Override
|
||||
public void readPersisted() {
|
||||
PreferencesPayload persisted = storage.initAndGetPersistedWithFileName("PreferencesPayload", 100);
|
||||
final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork();
|
||||
TradeCurrency preferredTradeCurrency;
|
||||
if (persisted != null) {
|
||||
prefPayload = persisted;
|
||||
|
@ -288,6 +295,15 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
if (referralIdFromOptions != null && !referralIdFromOptions.isEmpty())
|
||||
setReferralId(referralIdFromOptions);
|
||||
|
||||
if (fullDaoNodeFromOptions != null && !fullDaoNodeFromOptions.isEmpty())
|
||||
setDaoFullNode(fullDaoNodeFromOptions.toLowerCase().equals("true"));
|
||||
|
||||
if (rpcUserFromOptions != null && !rpcUserFromOptions.isEmpty())
|
||||
setRpcUser(rpcUserFromOptions);
|
||||
|
||||
if (rpcPasswordFromOptions != null && !rpcPasswordFromOptions.isEmpty())
|
||||
setRpcPw(rpcPasswordFromOptions);
|
||||
|
||||
// For users from old versions the 4 flags a false but we want to have it true by default
|
||||
// PhoneKeyAndToken is also null so we can use that to enable the flags
|
||||
if (prefPayload.getPhoneKeyAndToken() == null) {
|
||||
|
@ -596,6 +612,22 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
this.useStandbyModeProperty.set(useStandbyMode);
|
||||
}
|
||||
|
||||
public void setDaoFullNode(boolean value) {
|
||||
prefPayload.setDaoFullNode(value);
|
||||
persist();
|
||||
}
|
||||
|
||||
public void setRpcUser(String value) {
|
||||
prefPayload.setRpcUser(value);
|
||||
persist();
|
||||
}
|
||||
|
||||
public void setRpcPw(String value) {
|
||||
prefPayload.setRpcPw(value);
|
||||
persist();
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Getter
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -796,5 +828,11 @@ public final class Preferences implements PersistedDataHost, BridgeAddressProvid
|
|||
long getWithdrawalTxFeeInBytes();
|
||||
|
||||
void setUseStandbyMode(boolean useStandbyMode);
|
||||
|
||||
void setDaoFullNode(boolean value);
|
||||
|
||||
void setRpcUser(String value);
|
||||
|
||||
void setRpcPw(String value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,11 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
boolean useMarketNotifications = true;
|
||||
boolean usePriceNotifications = true;
|
||||
boolean useStandbyMode = false;
|
||||
boolean isDaoFullNode = false;
|
||||
@Nullable
|
||||
String rpcUser;
|
||||
@Nullable
|
||||
String rpcPw;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -164,7 +169,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
.setUseTradeNotifications(useTradeNotifications)
|
||||
.setUseMarketNotifications(useMarketNotifications)
|
||||
.setUsePriceNotifications(usePriceNotifications)
|
||||
.setUseStandbyMode(useStandbyMode);
|
||||
.setUseStandbyMode(useStandbyMode)
|
||||
.setIsDaoFullNode(isDaoFullNode);
|
||||
Optional.ofNullable(backupDirectory).ifPresent(builder::setBackupDirectory);
|
||||
Optional.ofNullable(preferredTradeCurrency).ifPresent(e -> builder.setPreferredTradeCurrency((PB.TradeCurrency) e.toProtoMessage()));
|
||||
Optional.ofNullable(offerBookChartScreenCurrencyCode).ifPresent(builder::setOfferBookChartScreenCurrencyCode);
|
||||
|
@ -177,6 +183,8 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
Optional.ofNullable(customBridges).ifPresent(builder::setCustomBridges);
|
||||
Optional.ofNullable(referralId).ifPresent(builder::setReferralId);
|
||||
Optional.ofNullable(phoneKeyAndToken).ifPresent(builder::setPhoneKeyAndToken);
|
||||
Optional.ofNullable(rpcUser).ifPresent(builder::setRpcUser);
|
||||
Optional.ofNullable(rpcPw).ifPresent(builder::setRpcPw);
|
||||
|
||||
return PB.PersistableEnvelope.newBuilder().setPreferencesPayload(builder).build();
|
||||
}
|
||||
|
@ -238,6 +246,9 @@ public final class PreferencesPayload implements PersistableEnvelope {
|
|||
proto.getUseTradeNotifications(),
|
||||
proto.getUseMarketNotifications(),
|
||||
proto.getUsePriceNotifications(),
|
||||
proto.getUseStandbyMode());
|
||||
proto.getUseStandbyMode(),
|
||||
proto.getIsDaoFullNode(),
|
||||
proto.getRpcUser().isEmpty() ? null : proto.getRpcUser(),
|
||||
proto.getRpcPw().isEmpty() ? null : proto.getRpcPw());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,8 +98,15 @@ public class BSFormatter {
|
|||
return formatCoin(coin, decimalPlaces, false, 0);
|
||||
}
|
||||
|
||||
public String formatCoin(long value, MonetaryFormat coinFormat) {
|
||||
return formatCoin(Coin.valueOf(value), -1, false, 0, coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits) {
|
||||
return formatCoin(coin, decimalPlaces, decimalAligned, maxNumberOfDigits, coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoin(Coin coin, int decimalPlaces, boolean decimalAligned, int maxNumberOfDigits, MonetaryFormat coinFormat) {
|
||||
String formattedCoin = "";
|
||||
|
||||
if (coin != null) {
|
||||
|
@ -122,6 +129,14 @@ public class BSFormatter {
|
|||
}
|
||||
|
||||
public String formatCoinWithCode(Coin coin) {
|
||||
return formatCoinWithCode(coin, coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(long value, MonetaryFormat coinFormat) {
|
||||
return formatCoinWithCode(Coin.valueOf(value), coinFormat);
|
||||
}
|
||||
|
||||
public String formatCoinWithCode(Coin coin, MonetaryFormat coinFormat) {
|
||||
if (coin != null) {
|
||||
try {
|
||||
// we don't use the code feature from coinFormat as it does automatic switching between mBTC and BTC and
|
||||
|
@ -137,6 +152,10 @@ public class BSFormatter {
|
|||
}
|
||||
|
||||
public Coin parseToCoin(String input) {
|
||||
return parseToCoin(input, coinFormat);
|
||||
}
|
||||
|
||||
public Coin parseToCoin(String input, MonetaryFormat coinFormat) {
|
||||
if (input != null && input.length() > 0) {
|
||||
try {
|
||||
return coinFormat.parse(cleanDoubleInput(input));
|
||||
|
@ -458,9 +477,13 @@ public class BSFormatter {
|
|||
}
|
||||
|
||||
public String formatDateTime(Date date) {
|
||||
return formatDateTime(date,
|
||||
DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale()),
|
||||
DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale()));
|
||||
}
|
||||
|
||||
public String formatDateTime(Date date, DateFormat dateFormatter, DateFormat timeFormatter) {
|
||||
if (date != null) {
|
||||
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT, getLocale());
|
||||
DateFormat timeFormatter = DateFormat.getTimeInstance(DateFormat.DEFAULT, getLocale());
|
||||
return dateFormatter.format(date) + " " + timeFormatter.format(date);
|
||||
} else {
|
||||
return "";
|
||||
|
@ -564,10 +587,10 @@ public class BSFormatter {
|
|||
}
|
||||
|
||||
public String formatDurationAsWords(long durationMillis) {
|
||||
return formatDurationAsWords(durationMillis, false);
|
||||
return formatDurationAsWords(durationMillis, false, true);
|
||||
}
|
||||
|
||||
public static String formatDurationAsWords(long durationMillis, boolean showSeconds) {
|
||||
public String formatDurationAsWords(long durationMillis, boolean showSeconds, boolean showZeroValues) {
|
||||
String format = "";
|
||||
String second = Res.get("time.second");
|
||||
String minute = Res.get("time.minute");
|
||||
|
@ -593,10 +616,19 @@ public class BSFormatter {
|
|||
duration = StringUtils.replacePattern(duration, "^1 " + minutes + "|\\b1 " + minutes, "1 " + minute);
|
||||
duration = StringUtils.replacePattern(duration, "^1 " + hours + "|\\b1 " + hours, "1 " + hour);
|
||||
duration = StringUtils.replacePattern(duration, "^1 " + days + "|\\b1 " + days, "1 " + day);
|
||||
|
||||
if (!showZeroValues) {
|
||||
duration = duration.replace(", 0 seconds", "");
|
||||
duration = duration.replace(", 0 minutes", "");
|
||||
duration = duration.replace(", 0 hours", "");
|
||||
duration = duration.replace("0 days", "");
|
||||
duration = duration.replace("0 hours, ", "");
|
||||
duration = duration.replace("0 minutes, ", "");
|
||||
duration = duration.replace("0 seconds", "");
|
||||
}
|
||||
return duration.trim();
|
||||
}
|
||||
|
||||
|
||||
public String booleanToYesNo(boolean value) {
|
||||
return value ? Res.get("shared.yes") : Res.get("shared.no");
|
||||
}
|
||||
|
|
|
@ -43,11 +43,14 @@ public class BsqFormatter extends BSFormatter {
|
|||
private final String prefix = "B";
|
||||
private final DecimalFormat amountFormat = new DecimalFormat("###,###,###.##");
|
||||
private final DecimalFormat marketCapFormat = new DecimalFormat("###,###,###");
|
||||
private final MonetaryFormat btcCoinFormat;
|
||||
|
||||
@Inject
|
||||
private BsqFormatter() {
|
||||
super();
|
||||
|
||||
btcCoinFormat = super.coinFormat;
|
||||
|
||||
final String baseCurrencyCode = BisqEnvironment.getBaseCurrencyNetwork().getCurrencyCode();
|
||||
switch (baseCurrencyCode) {
|
||||
case "BTC":
|
||||
|
@ -104,20 +107,14 @@ public class BsqFormatter extends BSFormatter {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public String formatBtcSatoshi(long satoshi) {
|
||||
return satoshi + " BTC Satoshi";
|
||||
public String formatBTCWithCode(long satoshi) {
|
||||
return super.formatCoinWithCode(satoshi, btcCoinFormat);
|
||||
}
|
||||
|
||||
public Coin parseSatoshiToBtc(String satoshi) {
|
||||
try {
|
||||
return Coin.valueOf(Long.valueOf(satoshi));
|
||||
} catch (Throwable e) {
|
||||
return Coin.ZERO;
|
||||
}
|
||||
public Coin parseToBTC(String input) {
|
||||
return super.parseToCoin(input, btcCoinFormat);
|
||||
}
|
||||
|
||||
|
||||
public String formatParamValue(Param param, long value) {
|
||||
switch (param) {
|
||||
case UNDEFINED:
|
||||
|
@ -125,8 +122,12 @@ public class BsqFormatter extends BSFormatter {
|
|||
|
||||
case DEFAULT_MAKER_FEE_BSQ:
|
||||
case DEFAULT_TAKER_FEE_BSQ:
|
||||
case MIN_MAKER_FEE_BSQ:
|
||||
case MIN_TAKER_FEE_BSQ:
|
||||
case DEFAULT_MAKER_FEE_BTC:
|
||||
case DEFAULT_TAKER_FEE_BTC:
|
||||
case MIN_MAKER_FEE_BTC:
|
||||
case MIN_TAKER_FEE_BTC:
|
||||
return formatToPercentWithSymbol(value / 10000d);
|
||||
|
||||
case PROPOSAL_FEE:
|
||||
|
|
|
@ -859,6 +859,13 @@ setting.preferences.daoOptions=DAO options
|
|||
setting.preferences.dao.resync.label=Rebuild DAO state from genesis tx:
|
||||
setting.preferences.dao.resync.button=Resync
|
||||
setting.preferences.dao.resync.popup=After an application restart the BSQ consensus state will be rebuilt from the genesis transaction.
|
||||
setting.preferences.dao.isDaoFullNode=Run Bisq as DAO full node
|
||||
setting.preferences.dao.rpcUser=RPC username
|
||||
setting.preferences.dao.rpcPw=RPC password
|
||||
setting.preferences.dao.fullNodeInfo=For running Bisq as DAO full node you need to have Bitcoin Core locally running \
|
||||
and configured with RPC and other requirements which are documented in ''{0}''.
|
||||
setting.preferences.dao.fullNodeInfo.ok=Open docs page
|
||||
setting.preferences.dao.fullNodeInfo.cancel=No, I stick with lite node mode
|
||||
|
||||
settings.net.btcHeader=Bitcoin network
|
||||
settings.net.p2pHeader=P2P network
|
||||
|
@ -1147,10 +1154,10 @@ dao.tab.proposals=Governance
|
|||
dao.tab.bonding=Bonding
|
||||
|
||||
dao.paidWithBsq=paid with BSQ
|
||||
dao.availableBsqBalance=Available BSQ balance
|
||||
dao.availableNonBsqBalance=Available non-BSQ balance
|
||||
dao.unverifiedBsqBalance=Unverified BSQ balance
|
||||
dao.lockedForVoteBalance=Locked for voting
|
||||
dao.availableBsqBalance=Available
|
||||
dao.availableNonBsqBalance=Available non-BSQ balance (BTC)
|
||||
dao.unverifiedBsqBalance=Unverified (awaiting block confirmation)
|
||||
dao.lockedForVoteBalance=Used for voting
|
||||
dao.lockedInBonds=Locked in bonds
|
||||
dao.totalBsqBalance=Total BSQ balance
|
||||
|
||||
|
@ -1167,7 +1174,7 @@ dao.cycle.proposal=Proposal phase:
|
|||
dao.cycle.blindVote=Blind vote phase:
|
||||
dao.cycle.voteReveal=Vote reveal phase:
|
||||
dao.cycle.voteResult=Vote result:
|
||||
dao.cycle.phaseDuration=Block: {0} - {1} ({2} - {3})
|
||||
dao.cycle.phaseDuration={0} blocks (≈{1}); Block {2} - {3} (≈{4} - ≈{5})
|
||||
|
||||
dao.cycle.info.headline=Information
|
||||
dao.cycle.info.details=Please note:\n\
|
||||
|
@ -1282,8 +1289,6 @@ dao.phase.PHASE_RESULT=Result phase
|
|||
dao.results.votes.table.header.stakeAndMerit=Vote weight
|
||||
dao.results.votes.table.header.stake=Stake
|
||||
dao.results.votes.table.header.merit=Earned
|
||||
dao.results.votes.table.header.blindVoteTxId=Blind vote Tx ID
|
||||
dao.results.votes.table.header.voteRevealTxId=Vote reveal Tx ID
|
||||
dao.results.votes.table.header.vote=Vote
|
||||
|
||||
dao.bonding.menuItem.bondedRoles=Bonded roles
|
||||
|
@ -1399,6 +1404,9 @@ dao.proposal.type.short.CONFISCATE_BOND=Confiscating a bond
|
|||
dao.proposal.details=Proposal details
|
||||
dao.proposal.selectedProposal=Selected proposal
|
||||
dao.proposal.active.header=Proposals of current cycle
|
||||
dao.proposal.active.remove.confirm=Are you sure you want to remove that proposal?\n\
|
||||
The already paid proposal fee will be lost.
|
||||
dao.proposal.active.remove.doRemove=Yes, remove my proposal
|
||||
dao.proposal.active.remove.failed=Could not remove proposal.
|
||||
dao.proposal.myVote.accept=Accept proposal
|
||||
dao.proposal.myVote.reject=Reject proposal
|
||||
|
@ -1407,7 +1415,7 @@ dao.proposal.myVote.merit=Vote weight from earned BSQ
|
|||
dao.proposal.myVote.stake=Vote weight from stake
|
||||
dao.proposal.myVote.blindVoteTxId=Blind vote transaction ID
|
||||
dao.proposal.myVote.revealTxId=Vote reveal transaction ID
|
||||
dao.proposal.myVote.stake.prompt=Available balance for voting: {0}
|
||||
dao.proposal.myVote.stake.prompt=Max. available balance for voting: {0}
|
||||
dao.proposal.votes.header=Vote on all proposals
|
||||
dao.proposal.votes.header.voted=My vote
|
||||
dao.proposal.myVote.button=Vote on all proposals
|
||||
|
@ -1426,11 +1434,14 @@ dao.proposal.display.txId=Proposal transaction ID:
|
|||
dao.proposal.display.proposalFee=Proposal fee:
|
||||
dao.proposal.display.myVote=My vote:
|
||||
dao.proposal.display.voteResult=Vote result summary:
|
||||
dao.proposal.display.bondedRoleComboBox.label=Choose bonded role type
|
||||
dao.proposal.display.bondedRoleComboBox.label=Bonded role type
|
||||
dao.proposal.display.requiredBondForRole.label=Required bond for role
|
||||
dao.proposal.display.tickerSymbol.label=Ticker Symbol
|
||||
|
||||
dao.proposal.table.header.proposalType=Proposal type
|
||||
dao.proposal.table.header.link=Link
|
||||
dao.proposal.table.icon.tooltip.removeProposal=Remove my proposal
|
||||
dao.proposal.table.icon.tooltip.changeVote=Current vote: ''{0}''. Change vote to: ''{1}''
|
||||
|
||||
dao.proposal.display.myVote.accepted=Accepted
|
||||
dao.proposal.display.myVote.rejected=Rejected
|
||||
|
@ -1441,7 +1452,7 @@ dao.proposal.voteResult.success=Accepted
|
|||
dao.proposal.voteResult.failed=Rejected
|
||||
dao.proposal.voteResult.summary=Result: {0}; Threshold: {1} (required > {2}); Quorum: {3} (required > {4})
|
||||
|
||||
dao.proposal.display.paramComboBox.label=Choose parameter
|
||||
dao.proposal.display.paramComboBox.label=Parameter
|
||||
dao.proposal.display.paramValue=Parameter value:
|
||||
|
||||
dao.proposal.display.confiscateBondComboBox.label=Choose bond
|
||||
|
@ -1456,31 +1467,37 @@ dao.wallet.menuItem.send=Send
|
|||
dao.wallet.menuItem.receive=Receive
|
||||
dao.wallet.menuItem.transactions=Transactions
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistics
|
||||
dao.wallet.dashboard.myBalance=My wallet balance
|
||||
dao.wallet.dashboard.distribution=Distribution of all BSQ
|
||||
dao.wallet.dashboard.locked=Global state of locked BSQ
|
||||
dao.wallet.dashboard.market=Market data
|
||||
dao.wallet.dashboard.txDetails=BSQ transactions details
|
||||
dao.wallet.dashboard.genesisBlockHeight=Genesis block height:
|
||||
dao.wallet.dashboard.genesisTxId=Genesis transaction ID:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
dao.wallet.dashboard.compRequestIssueAmount=Issued amount from compensation requests:
|
||||
dao.wallet.dashboard.availableAmount=Total available amount:
|
||||
dao.wallet.dashboard.burntAmount=Amount of burned BSQ (fees):
|
||||
dao.wallet.dashboard.totalLockedUpAmount=Amount of locked up BSQ (bonds):
|
||||
dao.wallet.dashboard.totalUnlockingAmount=Amount of unlocking BSQ (bonds):
|
||||
dao.wallet.dashboard.totalUnlockedAmount=Amount of unlocked BSQ (bonds):
|
||||
dao.wallet.dashboard.genesisIssueAmount=BSQ issued at genesis transaction:
|
||||
dao.wallet.dashboard.compRequestIssueAmount=BSQ issued for compensation requests:
|
||||
dao.wallet.dashboard.availableAmount=Total available BSQ:
|
||||
dao.wallet.dashboard.burntAmount=Burned BSQ (fees):
|
||||
dao.wallet.dashboard.totalLockedUpAmount=Locked up in bonds:
|
||||
dao.wallet.dashboard.totalUnlockingAmount=Unlocking BSQ from bonds:
|
||||
dao.wallet.dashboard.totalUnlockedAmount=Unlocked BSQ from bonds:
|
||||
dao.wallet.dashboard.allTx=No. of all BSQ transactions:
|
||||
dao.wallet.dashboard.utxo=No. of all unspent transaction outputs:
|
||||
dao.wallet.dashboard.burntTx=No. of all fee payments transactions (burnt):
|
||||
dao.wallet.dashboard.price=Price:
|
||||
dao.wallet.dashboard.marketCap=Market capitalisation:
|
||||
dao.wallet.dashboard.issuanceTx=No. of all issuance transactions:
|
||||
dao.wallet.dashboard.burntTx=No. of all fee payments transactions:
|
||||
dao.wallet.dashboard.price=Latest BSQ/BTC trade price (in Bisq):
|
||||
dao.wallet.dashboard.marketCap=Market capitalisation (based on trade price):
|
||||
|
||||
dao.wallet.receive.fundBSQWallet=Fund Bisq BSQ wallet
|
||||
dao.wallet.receive.fundYourWallet=Fund your BSQ wallet
|
||||
dao.wallet.receive.bsqAddress=BSQ address
|
||||
|
||||
dao.wallet.send.sendFunds=Send funds
|
||||
dao.wallet.send.sendBtcFunds=Send non-BSQ funds
|
||||
dao.wallet.send.sendBtcFunds=Send non-BSQ funds (BTC)
|
||||
dao.wallet.send.amount=Amount in BSQ:
|
||||
dao.wallet.send.btcAmount=Amount in BTC Satoshi:
|
||||
dao.wallet.send.btcAmount=Amount in BTC (non-BSQ funds):
|
||||
dao.wallet.send.setAmount=Set amount to withdraw (min. amount is {0})
|
||||
dao.wallet.send.setBtcAmount=Set amount in BTC Satoshi to withdraw (min. amount is {0} Satoshi)
|
||||
dao.wallet.send.setBtcAmount=Set amount in BTC to withdraw (min. amount is {0})
|
||||
dao.wallet.send.receiverAddress=Receiver's BSQ address:
|
||||
dao.wallet.send.receiverBtcAddress=Receiver's BTC address:
|
||||
dao.wallet.send.setDestinationAddress=Fill in your destination address
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Senden
|
|||
dao.wallet.menuItem.receive=Empfangen
|
||||
dao.wallet.menuItem.transactions=Transaktionen
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistiken
|
||||
dao.wallet.dashboard.distribution=Statistiken
|
||||
dao.wallet.dashboard.genesisBlockHeight=Ursprungsblock-Höhe:
|
||||
dao.wallet.dashboard.genesisTxId=Ursprungstransaktion-ID:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Ausgestellter Betrag in Ursprungstransaktion:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Αποστολή
|
|||
dao.wallet.menuItem.receive=Λήψη
|
||||
dao.wallet.menuItem.transactions=Συναλλαγές
|
||||
|
||||
dao.wallet.dashboard.statistics=Στατιστικά
|
||||
dao.wallet.dashboard.distribution=Στατιστικά
|
||||
dao.wallet.dashboard.genesisBlockHeight=Ύψος μπλοκ Genesis:
|
||||
dao.wallet.dashboard.genesisTxId=Ταυτότητα συναλλαγής genesis:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Enviar
|
|||
dao.wallet.menuItem.receive=Recibir
|
||||
dao.wallet.menuItem.transactions=Transacciones
|
||||
|
||||
dao.wallet.dashboard.statistics=Estadísticas
|
||||
dao.wallet.dashboard.distribution=Estadísticas
|
||||
dao.wallet.dashboard.genesisBlockHeight=Altura de bloque génesis:
|
||||
dao.wallet.dashboard.genesisTxId=ID de transacción génesis:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=ارسال
|
|||
dao.wallet.menuItem.receive=دریافت
|
||||
dao.wallet.menuItem.transactions=تراکنش ها
|
||||
|
||||
dao.wallet.dashboard.statistics=آمار
|
||||
dao.wallet.dashboard.distribution=آمار
|
||||
dao.wallet.dashboard.genesisBlockHeight=ارتفاع جنسیس بلاک:
|
||||
dao.wallet.dashboard.genesisTxId=شناسه تراکنش جنسیس:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1033,7 +1033,7 @@ dao.wallet.menuItem.send=Envoyer
|
|||
dao.wallet.menuItem.receive=Recevoir
|
||||
dao.wallet.menuItem.transactions=Transactions
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistics
|
||||
dao.wallet.dashboard.distribution=Statistics
|
||||
dao.wallet.dashboard.genesisBlockHeight=Genesis block height:
|
||||
dao.wallet.dashboard.genesisTxId=Genesis transaction ID:
|
||||
dao.wallet.dashboard.issuedAmount=Total issued amount:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Küldés
|
|||
dao.wallet.menuItem.receive=Fogadd:
|
||||
dao.wallet.menuItem.transactions=Tranzakciók
|
||||
|
||||
dao.wallet.dashboard.statistics=Statisztika
|
||||
dao.wallet.dashboard.distribution=Statisztika
|
||||
dao.wallet.dashboard.genesisBlockHeight=Genesis blokk magassága:
|
||||
dao.wallet.dashboard.genesisTxId=Genesis tranzakció azonosítója:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Enviar
|
|||
dao.wallet.menuItem.receive=Receber
|
||||
dao.wallet.menuItem.transactions=Transações
|
||||
|
||||
dao.wallet.dashboard.statistics=Estatísticas
|
||||
dao.wallet.dashboard.distribution=Estatísticas
|
||||
dao.wallet.dashboard.genesisBlockHeight=Altura do bloco gênese:
|
||||
dao.wallet.dashboard.genesisTxId=ID da transação gênese:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Trimite
|
|||
dao.wallet.menuItem.receive=Încasează
|
||||
dao.wallet.menuItem.transactions=Tranzacții
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistici
|
||||
dao.wallet.dashboard.distribution=Statistici
|
||||
dao.wallet.dashboard.genesisBlockHeight=Înălțimea blocului geneză:
|
||||
dao.wallet.dashboard.genesisTxId=Codul tranzacției geneză:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Послать
|
|||
dao.wallet.menuItem.receive=Получить
|
||||
dao.wallet.menuItem.transactions=Транзакции
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistics
|
||||
dao.wallet.dashboard.distribution=Statistics
|
||||
dao.wallet.dashboard.genesisBlockHeight=Номер исходного блока:
|
||||
dao.wallet.dashboard.genesisTxId=Идентификатор зачисления на счёт
|
||||
dao.wallet.dashboard.genesisIssueAmount=Сумма выпущенная в исходной транзакции:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Pošalji
|
|||
dao.wallet.menuItem.receive=Primi
|
||||
dao.wallet.menuItem.transactions=Transakcije
|
||||
|
||||
dao.wallet.dashboard.statistics=Statistics
|
||||
dao.wallet.dashboard.distribution=Statistics
|
||||
dao.wallet.dashboard.genesisBlockHeight=Genesis block height:
|
||||
dao.wallet.dashboard.genesisTxId=Genesis transaction ID:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=ส่ง
|
|||
dao.wallet.menuItem.receive=รับ
|
||||
dao.wallet.menuItem.transactions=การทำธุรกรรม
|
||||
|
||||
dao.wallet.dashboard.statistics=สถิติ
|
||||
dao.wallet.dashboard.distribution=สถิติ
|
||||
dao.wallet.dashboard.genesisBlockHeight=ความสูงของบ็อกต้นกำเนิด (Genesis block):
|
||||
dao.wallet.dashboard.genesisTxId=ID การทำธุรกรรมต้นกำเนิด:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=Gửi
|
|||
dao.wallet.menuItem.receive=Nhận
|
||||
dao.wallet.menuItem.transactions=Giao dịch
|
||||
|
||||
dao.wallet.dashboard.statistics=Số liệu thống kê
|
||||
dao.wallet.dashboard.distribution=Số liệu thống kê
|
||||
dao.wallet.dashboard.genesisBlockHeight=Chiều cao block ban đầu:
|
||||
dao.wallet.dashboard.genesisTxId=ID giao dịch ban đầu:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -1291,7 +1291,7 @@ dao.wallet.menuItem.send=发送
|
|||
dao.wallet.menuItem.receive=接收
|
||||
dao.wallet.menuItem.transactions=交易记录
|
||||
|
||||
dao.wallet.dashboard.statistics=统计
|
||||
dao.wallet.dashboard.distribution=统计
|
||||
dao.wallet.dashboard.genesisBlockHeight=创始块高度:
|
||||
dao.wallet.dashboard.genesisTxId=创始交易ID:
|
||||
dao.wallet.dashboard.genesisIssueAmount=Issued amount at genesis transaction:
|
||||
|
|
|
@ -69,7 +69,7 @@ public class PreferencesTest {
|
|||
storage = mock(Storage.class);
|
||||
bisqEnvironment = mock(BisqEnvironment.class);
|
||||
|
||||
preferences = new Preferences(storage, bisqEnvironment, null, null, null);
|
||||
preferences = new Preferences(storage, bisqEnvironment, null, null, null, null, null, null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -17,11 +17,12 @@
|
|||
|
||||
package bisq.desktop.components;
|
||||
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.Parent;
|
||||
|
@ -61,7 +62,7 @@ public class InfoDisplay extends Parent {
|
|||
|
||||
private boolean useReadMore;
|
||||
|
||||
private final Label icon = AwesomeDude.createIconLabel(AwesomeIcon.INFO_SIGN);
|
||||
private final Label icon = FormBuilder.getIcon(AwesomeIcon.INFO_SIGN);
|
||||
private final TextFlow textFlow;
|
||||
private final Label label;
|
||||
private final Hyperlink link;
|
||||
|
|
|
@ -156,6 +156,13 @@ public class TxIdTextField extends AnchorPane {
|
|||
txConfidenceIndicator.setVisible(true);
|
||||
AnchorPane.setRightAnchor(txConfidenceIndicator, 0.0);
|
||||
}
|
||||
} else {
|
||||
//TODO we should show some placeholder in case of a tx which we are not aware of but which can be
|
||||
// confirmed already. This is for instance the case of the other peers trade fee tx, as it is not related
|
||||
// to our wallet we don't have a confidence object but we should show that it is in a unknown state instead
|
||||
// of not showing anything which causes confusion that the tx was not broadcasted. Best would be to request
|
||||
// it from a block explorer service but that is a bit too heavy for that use case...
|
||||
// Maybe a question mark with a tooltip explaining why we don't know about the confidence might be ok...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -126,9 +126,9 @@ public class PhasesView implements DaoStateListener {
|
|||
private void applyData(int height) {
|
||||
if (height > 0) {
|
||||
phaseBarsItems.forEach(item -> {
|
||||
int firstBlock = daoFacade.getFirstBlockOfPhase(height, item.getPhase());
|
||||
int lastBlock = daoFacade.getLastBlockOfPhase(height, item.getPhase());
|
||||
final int duration = daoFacade.getDurationForPhase(item.getPhase());
|
||||
int firstBlock = daoFacade.getFirstBlockOfPhaseForDisplay(height, item.getPhase());
|
||||
int lastBlock = daoFacade.getLastBlockOfPhaseForDisplay(height, item.getPhase());
|
||||
int duration = daoFacade.getDurationForPhaseForDisplay(item.getPhase());
|
||||
item.setPeriodRange(firstBlock, lastBlock, duration);
|
||||
double progress = 0;
|
||||
if (height >= firstBlock && height <= lastBlock) {
|
||||
|
|
|
@ -19,15 +19,13 @@ package bisq.desktop.main.dao.governance;
|
|||
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.TxIdTextField;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
import bisq.desktop.util.validation.BsqAddressValidator;
|
||||
import bisq.desktop.util.validation.BsqValidator;
|
||||
|
||||
import bisq.core.btc.BaseCurrencyNetwork;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.ballot.Ballot;
|
||||
import bisq.core.dao.governance.ballot.vote.Vote;
|
||||
|
@ -65,6 +63,7 @@ import javafx.scene.layout.GridPane;
|
|||
import javafx.scene.layout.Priority;
|
||||
|
||||
import javafx.geometry.HPos;
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
|
@ -83,7 +82,10 @@ import lombok.extern.slf4j.Slf4j;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.*;
|
||||
import static bisq.desktop.util.FormBuilder.addLabelHyperlinkWithIcon;
|
||||
import static bisq.desktop.util.FormBuilder.addLabelInputTextField;
|
||||
import static bisq.desktop.util.FormBuilder.addLabelTextField;
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
|
||||
|
@ -95,17 +97,16 @@ import bisq.asset.Asset;
|
|||
public class ProposalDisplay {
|
||||
private final GridPane gridPane;
|
||||
private final BsqFormatter bsqFormatter;
|
||||
private final BsqWalletService bsqWalletService;
|
||||
private final DaoFacade daoFacade;
|
||||
|
||||
@Nullable
|
||||
private TextField uidTextField, proposalFeeTextField;
|
||||
private TextField proposalFeeTextField, comboBoxValueTextField, requiredBondForRoleTextField;
|
||||
private TextField proposalTypeTextField, myVoteTextField, voteResultTextField;
|
||||
private Label myVoteLabel, voteResultLabel;
|
||||
public InputTextField nameTextField;
|
||||
public InputTextField linkInputTextField;
|
||||
@Nullable
|
||||
public InputTextField requestedBsqTextField, bsqAddressTextField, paramValueTextField;
|
||||
public InputTextField requestedBsqTextField, paramValueTextField;
|
||||
@Nullable
|
||||
public ComboBox<Param> paramComboBox;
|
||||
@Nullable
|
||||
|
@ -118,8 +119,6 @@ public class ProposalDisplay {
|
|||
@Getter
|
||||
private int gridRow;
|
||||
private HyperlinkWithIcon linkHyperlinkWithIcon;
|
||||
@Nullable
|
||||
private TxIdTextField txIdTextField;
|
||||
private int gridRowStartIndex;
|
||||
private final List<Runnable> inputChangedListeners = new ArrayList<>();
|
||||
@Getter
|
||||
|
@ -129,12 +128,13 @@ public class ProposalDisplay {
|
|||
private final ChangeListener<Boolean> focusOutListener;
|
||||
private final ChangeListener<Object> inputListener;
|
||||
private ChangeListener<Param> paramChangeListener;
|
||||
private ChangeListener<BondedRoleType> requiredBondForRoleListener;
|
||||
private TitledGroupBg titledGroupBg;
|
||||
private int titledGroupBgRowSpan;
|
||||
|
||||
public ProposalDisplay(GridPane gridPane, BsqFormatter bsqFormatter, BsqWalletService bsqWalletService,
|
||||
DaoFacade daoFacade) {
|
||||
public ProposalDisplay(GridPane gridPane, BsqFormatter bsqFormatter, DaoFacade daoFacade) {
|
||||
this.gridPane = gridPane;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.daoFacade = daoFacade;
|
||||
|
||||
// focusOutListener = observable -> inputChangedListeners.forEach(Runnable::run);
|
||||
|
@ -159,41 +159,31 @@ public class ProposalDisplay {
|
|||
removeAllFields();
|
||||
this.gridRowStartIndex = gridRowStartIndex;
|
||||
this.gridRow = gridRowStartIndex;
|
||||
int titledGroupBgRowSpan = 6;
|
||||
titledGroupBgRowSpan = 5;
|
||||
|
||||
switch (proposalType) {
|
||||
case COMPENSATION_REQUEST:
|
||||
titledGroupBgRowSpan += 1;
|
||||
break;
|
||||
case CHANGE_PARAM:
|
||||
titledGroupBgRowSpan += 1;
|
||||
titledGroupBgRowSpan = 6;
|
||||
break;
|
||||
case BONDED_ROLE:
|
||||
titledGroupBgRowSpan = 6;
|
||||
break;
|
||||
case CONFISCATE_BOND:
|
||||
break;
|
||||
case GENERIC:
|
||||
titledGroupBgRowSpan -= 1;
|
||||
titledGroupBgRowSpan = 4;
|
||||
break;
|
||||
case REMOVE_ASSET:
|
||||
break;
|
||||
}
|
||||
|
||||
// at isMakeProposalScreen we show fee but no uid and txID (+1)
|
||||
// otherwise we don't show fee but show uid and txID (+2)
|
||||
if (isMakeProposalScreen)
|
||||
titledGroupBgRowSpan += 1;
|
||||
else
|
||||
titledGroupBgRowSpan += 2;
|
||||
|
||||
addTitledGroupBg(gridPane, gridRow, titledGroupBgRowSpan, title, top);
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, titledGroupBgRowSpan, title, top);
|
||||
double proposalTypeTop = top == Layout.GROUP_DISTANCE ? Layout.FIRST_ROW_AND_GROUP_DISTANCE : Layout.FIRST_ROW_DISTANCE;
|
||||
proposalTypeTextField = addLabelTextField(gridPane, gridRow,
|
||||
Res.getWithCol("dao.proposal.display.type"), proposalType.getDisplayName(), proposalTypeTop).second;
|
||||
|
||||
if (!isMakeProposalScreen)
|
||||
uidTextField = addLabelTextField(gridPane, ++gridRow, Res.getWithCol("shared.id")).second;
|
||||
|
||||
nameTextField = addLabelInputTextField(gridPane, ++gridRow, Res.get("dao.proposal.display.name")).second;
|
||||
nameTextField.setValidator(new InputValidator());
|
||||
inputControls.add(nameTextField);
|
||||
|
@ -210,6 +200,7 @@ public class ProposalDisplay {
|
|||
linkHyperlinkWithIcon.setVisible(false);
|
||||
linkHyperlinkWithIcon.setManaged(false);
|
||||
|
||||
int comboBoxValueTextFieldIndex = -1;
|
||||
switch (proposalType) {
|
||||
case COMPENSATION_REQUEST:
|
||||
requestedBsqTextField = addLabelInputTextField(gridPane, ++gridRow,
|
||||
|
@ -220,19 +211,12 @@ public class ProposalDisplay {
|
|||
checkNotNull(requestedBsqTextField, "requestedBsqTextField must not be null");
|
||||
requestedBsqTextField.setValidator(bsqValidator);
|
||||
inputControls.add(requestedBsqTextField);
|
||||
|
||||
// TODO validator, addressTF
|
||||
bsqAddressTextField = addLabelInputTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.proposal.display.bsqAddress")).second;
|
||||
checkNotNull(bsqAddressTextField, "bsqAddressTextField must not be null");
|
||||
bsqAddressTextField.setText("B" + bsqWalletService.getUnusedAddress().toBase58());
|
||||
bsqAddressTextField.setValidator(new BsqAddressValidator(bsqFormatter));
|
||||
inputControls.add(bsqAddressTextField);
|
||||
break;
|
||||
case CHANGE_PARAM:
|
||||
checkNotNull(gridPane, "gridPane must not be null");
|
||||
paramComboBox = FormBuilder.<Param>addLabelComboBox(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.proposal.display.paramComboBox.label")).second;
|
||||
comboBoxValueTextFieldIndex = gridRow;
|
||||
checkNotNull(paramComboBox, "paramComboBox must not be null");
|
||||
List<Param> list = Arrays.stream(Param.values())
|
||||
.filter(e -> e != Param.UNDEFINED && e != Param.PHASE_UNDEFINED)
|
||||
|
@ -252,7 +236,6 @@ public class ProposalDisplay {
|
|||
comboBoxes.add(paramComboBox);
|
||||
paramValueTextField = addLabelInputTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.proposal.display.paramValue")).second;
|
||||
//noinspection ConstantConditions
|
||||
|
||||
//TODO use custom param validator
|
||||
paramValueTextField.setValidator(new InputValidator());
|
||||
|
@ -271,6 +254,7 @@ public class ProposalDisplay {
|
|||
case BONDED_ROLE:
|
||||
bondedRoleTypeComboBox = FormBuilder.<BondedRoleType>addLabelComboBox(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.proposal.display.bondedRoleComboBox.label")).second;
|
||||
comboBoxValueTextFieldIndex = gridRow;
|
||||
checkNotNull(bondedRoleTypeComboBox, "bondedRoleTypeComboBox must not be null");
|
||||
bondedRoleTypeComboBox.setItems(FXCollections.observableArrayList(BondedRoleType.values()));
|
||||
bondedRoleTypeComboBox.setConverter(new StringConverter<>() {
|
||||
|
@ -285,10 +269,21 @@ public class ProposalDisplay {
|
|||
}
|
||||
});
|
||||
comboBoxes.add(bondedRoleTypeComboBox);
|
||||
requiredBondForRoleTextField = FormBuilder.addLabelTextField(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.proposal.display.requiredBondForRole.label")).second;
|
||||
|
||||
requiredBondForRoleListener = (observable, oldValue, newValue) -> {
|
||||
if (newValue != null) {
|
||||
requiredBondForRoleTextField.setText(bsqFormatter.formatCoinWithCode(Coin.valueOf(newValue.getRequiredBond())));
|
||||
}
|
||||
};
|
||||
bondedRoleTypeComboBox.getSelectionModel().selectedItemProperty().addListener(requiredBondForRoleListener);
|
||||
|
||||
break;
|
||||
case CONFISCATE_BOND:
|
||||
confiscateBondComboBox = FormBuilder.<BondedRole>addLabelComboBox(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.proposal.display.confiscateBondComboBox.label")).second;
|
||||
comboBoxValueTextFieldIndex = gridRow;
|
||||
checkNotNull(confiscateBondComboBox, "confiscateBondComboBox must not be null");
|
||||
confiscateBondComboBox.setItems(FXCollections.observableArrayList(daoFacade.getValidBondedRoleList()));
|
||||
confiscateBondComboBox.setConverter(new StringConverter<>() {
|
||||
|
@ -309,6 +304,7 @@ public class ProposalDisplay {
|
|||
case REMOVE_ASSET:
|
||||
assetComboBox = FormBuilder.<Asset>addLabelComboBox(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.proposal.display.assetComboBox.label")).second;
|
||||
comboBoxValueTextFieldIndex = gridRow;
|
||||
checkNotNull(assetComboBox, "assetComboBox must not be null");
|
||||
List<Asset> assetList = CurrencyUtil.getAssetRegistry().stream()
|
||||
.filter(e -> !e.getTickerSymbol().equals("BSQ"))
|
||||
|
@ -331,10 +327,17 @@ public class ProposalDisplay {
|
|||
break;
|
||||
}
|
||||
|
||||
if (!isMakeProposalScreen) {
|
||||
txIdTextField = addLabelTxIdTextField(gridPane, ++gridRow,
|
||||
Res.get("dao.proposal.display.txId"), "").second;
|
||||
txIdTextField.setBsq(true);
|
||||
if (comboBoxValueTextFieldIndex > -1) {
|
||||
comboBoxValueTextField = new TextField("");
|
||||
comboBoxValueTextField.setEditable(false);
|
||||
comboBoxValueTextField.setMouseTransparent(true);
|
||||
comboBoxValueTextField.setFocusTraversable(false);
|
||||
comboBoxValueTextField.setVisible(false);
|
||||
comboBoxValueTextField.setManaged(false);
|
||||
GridPane.setRowIndex(comboBoxValueTextField, comboBoxValueTextFieldIndex);
|
||||
GridPane.setColumnIndex(comboBoxValueTextField, 1);
|
||||
GridPane.setMargin(comboBoxValueTextField, new Insets(top, 0, 0, 0));
|
||||
gridPane.getChildren().add(comboBoxValueTextField);
|
||||
}
|
||||
|
||||
if (isMakeProposalScreen) {
|
||||
|
@ -379,6 +382,8 @@ public class ProposalDisplay {
|
|||
}
|
||||
|
||||
public void applyEvaluatedProposal(@Nullable EvaluatedProposal evaluatedProposal) {
|
||||
GridPane.setRowSpan(titledGroupBg, titledGroupBgRowSpan + 1);
|
||||
|
||||
boolean isEvaluatedProposalNotNull = evaluatedProposal != null;
|
||||
if (isEvaluatedProposalNotNull) {
|
||||
String result = evaluatedProposal.isAccepted() ? Res.get("dao.proposal.voteResult.success") :
|
||||
|
@ -426,26 +431,25 @@ public class ProposalDisplay {
|
|||
|
||||
public void applyProposalPayload(Proposal proposal) {
|
||||
proposalTypeTextField.setText(proposal.getType().getDisplayName());
|
||||
if (uidTextField != null)
|
||||
uidTextField.setText(proposal.getTxId());
|
||||
|
||||
nameTextField.setText(proposal.getName());
|
||||
linkInputTextField.setVisible(false);
|
||||
linkInputTextField.setManaged(false);
|
||||
linkHyperlinkWithIcon.setVisible(true);
|
||||
linkHyperlinkWithIcon.setManaged(true);
|
||||
linkHyperlinkWithIcon.setText(proposal.getLink());
|
||||
linkHyperlinkWithIcon.setOnAction(e -> GUIUtil.openWebPage(proposal.getLink()));
|
||||
if (linkHyperlinkWithIcon != null) {
|
||||
linkHyperlinkWithIcon.setVisible(true);
|
||||
linkHyperlinkWithIcon.setManaged(true);
|
||||
linkHyperlinkWithIcon.setText(proposal.getLink());
|
||||
linkHyperlinkWithIcon.setOnAction(e -> GUIUtil.openWebPage(proposal.getLink()));
|
||||
}
|
||||
|
||||
if (proposal instanceof CompensationProposal) {
|
||||
CompensationProposal compensationProposal = (CompensationProposal) proposal;
|
||||
checkNotNull(requestedBsqTextField, "requestedBsqTextField must not be null");
|
||||
requestedBsqTextField.setText(bsqFormatter.formatCoinWithCode(compensationProposal.getRequestedBsq()));
|
||||
if (bsqAddressTextField != null)
|
||||
bsqAddressTextField.setText(compensationProposal.getBsqAddress());
|
||||
} else if (proposal instanceof ChangeParamProposal) {
|
||||
ChangeParamProposal changeParamProposal = (ChangeParamProposal) proposal;
|
||||
checkNotNull(paramComboBox, "paramComboBox must not be null");
|
||||
paramComboBox.getSelectionModel().select(changeParamProposal.getParam());
|
||||
comboBoxValueTextField.setText(paramComboBox.getConverter().toString(changeParamProposal.getParam()));
|
||||
checkNotNull(paramValueTextField, "paramValueTextField must not be null");
|
||||
paramValueTextField.setText(bsqFormatter.formatParamValue(changeParamProposal.getParam(), changeParamProposal.getParamValue()));
|
||||
} else if (proposal instanceof BondedRoleProposal) {
|
||||
|
@ -453,26 +457,29 @@ public class ProposalDisplay {
|
|||
checkNotNull(bondedRoleTypeComboBox, "bondedRoleComboBox must not be null");
|
||||
BondedRole bondedRole = bondedRoleProposal.getBondedRole();
|
||||
bondedRoleTypeComboBox.getSelectionModel().select(bondedRole.getBondedRoleType());
|
||||
comboBoxValueTextField.setText(bondedRoleTypeComboBox.getConverter().toString(bondedRole.getBondedRoleType()));
|
||||
requiredBondForRoleTextField.setText(bsqFormatter.formatCoin(Coin.valueOf(bondedRole.getBondedRoleType().getRequiredBond())));
|
||||
} else if (proposal instanceof ConfiscateBondProposal) {
|
||||
ConfiscateBondProposal confiscateBondProposal = (ConfiscateBondProposal) proposal;
|
||||
checkNotNull(confiscateBondComboBox, "confiscateBondComboBox must not be null");
|
||||
|
||||
daoFacade.getBondedRoleFromHash(confiscateBondProposal.getHash())
|
||||
.ifPresent(bondedRole -> confiscateBondComboBox.getSelectionModel().select(bondedRole));
|
||||
.ifPresent(bondedRole -> {
|
||||
confiscateBondComboBox.getSelectionModel().select(bondedRole);
|
||||
comboBoxValueTextField.setText(confiscateBondComboBox.getConverter().toString(bondedRole));
|
||||
});
|
||||
} else if (proposal instanceof GenericProposal) {
|
||||
// do nothing
|
||||
} else if (proposal instanceof RemoveAssetProposal) {
|
||||
RemoveAssetProposal removeAssetProposal = (RemoveAssetProposal) proposal;
|
||||
checkNotNull(assetComboBox, "assetComboBox must not be null");
|
||||
CurrencyUtil.findAsset(removeAssetProposal.getTickerSymbol(), BaseCurrencyNetwork.BTC_MAINNET)
|
||||
.ifPresent(asset -> assetComboBox.getSelectionModel().select(asset));
|
||||
}
|
||||
int chainHeight;
|
||||
if (txIdTextField != null) {
|
||||
txIdTextField.setup(proposal.getTxId());
|
||||
chainHeight = daoFacade.getChainHeight();
|
||||
} else {
|
||||
chainHeight = daoFacade.getTx(proposal.getTxId()).map(Tx::getBlockHeight).orElse(0);
|
||||
.ifPresent(asset -> {
|
||||
assetComboBox.getSelectionModel().select(asset);
|
||||
comboBoxValueTextField.setText(assetComboBox.getConverter().toString(asset));
|
||||
});
|
||||
}
|
||||
int chainHeight = daoFacade.getTx(proposal.getTxId()).map(Tx::getBlockHeight).orElse(daoFacade.getChainHeight());
|
||||
if (proposalFeeTextField != null)
|
||||
proposalFeeTextField.setText(bsqFormatter.formatCoinWithCode(daoFacade.getProposalFee(chainHeight)));
|
||||
}
|
||||
|
@ -504,30 +511,42 @@ public class ProposalDisplay {
|
|||
|
||||
if (paramComboBox != null && paramChangeListener != null)
|
||||
paramComboBox.getSelectionModel().selectedItemProperty().removeListener(paramChangeListener);
|
||||
|
||||
if (bondedRoleTypeComboBox != null && requiredBondForRoleListener != null)
|
||||
bondedRoleTypeComboBox.getSelectionModel().selectedItemProperty().removeListener(requiredBondForRoleListener);
|
||||
}
|
||||
|
||||
public void clearForm() {
|
||||
inputControls.stream().filter(Objects::nonNull).forEach(TextInputControl::clear);
|
||||
|
||||
if (uidTextField != null) uidTextField.clear();
|
||||
if (linkHyperlinkWithIcon != null) linkHyperlinkWithIcon.clear();
|
||||
if (txIdTextField != null) txIdTextField.cleanup();
|
||||
if (linkHyperlinkWithIcon != null)
|
||||
linkHyperlinkWithIcon.clear();
|
||||
|
||||
comboBoxes.stream()
|
||||
.filter(Objects::nonNull).forEach(comboBox -> {
|
||||
comboBoxes.stream().filter(Objects::nonNull).forEach(comboBox -> {
|
||||
comboBox.getSelectionModel().clearSelection();
|
||||
});
|
||||
}
|
||||
|
||||
public void setEditable(boolean isEditable) {
|
||||
inputControls.stream().filter(Objects::nonNull).forEach(e -> e.setEditable(isEditable));
|
||||
comboBoxes.stream().filter(Objects::nonNull).forEach(comboBox -> comboBox.setDisable(!isEditable));
|
||||
comboBoxes.stream().filter(Objects::nonNull).forEach(comboBox -> {
|
||||
comboBox.setVisible(isEditable);
|
||||
comboBox.setManaged(isEditable);
|
||||
|
||||
if (comboBoxValueTextField != null) {
|
||||
comboBoxValueTextField.setVisible(!isEditable);
|
||||
comboBoxValueTextField.setManaged(!isEditable);
|
||||
}
|
||||
});
|
||||
|
||||
linkInputTextField.setVisible(true);
|
||||
linkInputTextField.setManaged(true);
|
||||
linkHyperlinkWithIcon.setVisible(false);
|
||||
linkHyperlinkWithIcon.setManaged(false);
|
||||
linkHyperlinkWithIcon.setOnAction(null);
|
||||
|
||||
if (linkHyperlinkWithIcon != null) {
|
||||
linkHyperlinkWithIcon.setVisible(false);
|
||||
linkHyperlinkWithIcon.setManaged(false);
|
||||
linkHyperlinkWithIcon.setOnAction(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllFields() {
|
||||
|
|
|
@ -34,7 +34,10 @@ import javax.inject.Inject;
|
|||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addLabelTextField;
|
||||
import static bisq.desktop.util.FormBuilder.addMultilineLabel;
|
||||
|
@ -134,11 +137,15 @@ public class ProposalDashboardView extends ActivatableView<GridPane, Void> imple
|
|||
}
|
||||
|
||||
private String getPhaseDuration(int height, DaoPhase.Phase phase) {
|
||||
final long start = daoFacade.getFirstBlockOfPhase(height, phase);
|
||||
final long end = daoFacade.getLastBlockOfPhase(height, phase);
|
||||
long start = daoFacade.getFirstBlockOfPhaseForDisplay(height, phase);
|
||||
long end = daoFacade.getLastBlockOfPhaseForDisplay(height, phase);
|
||||
long duration = daoFacade.getDurationForPhaseForDisplay(phase);
|
||||
long now = new Date().getTime();
|
||||
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L));
|
||||
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L));
|
||||
return Res.get("dao.cycle.phaseDuration", start, end, startDateTime, endDateTime);
|
||||
SimpleDateFormat dateFormatter = new SimpleDateFormat("dd MMM", Locale.getDefault());
|
||||
SimpleDateFormat timeFormatter = new SimpleDateFormat("hh:mm", Locale.getDefault());
|
||||
String startDateTime = formatter.formatDateTime(new Date(now + (start - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String endDateTime = formatter.formatDateTime(new Date(now + (end - height) * 10 * 60 * 1000L), dateFormatter, timeFormatter);
|
||||
String durationTime = formatter.formatDurationAsWords(duration * 10 * 60 * 1000, false, false);
|
||||
return Res.get("dao.cycle.phaseDuration", duration, durationTime, start, end, startDateTime, endDateTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,12 +260,9 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
|||
case COMPENSATION_REQUEST:
|
||||
checkNotNull(proposalDisplay.requestedBsqTextField,
|
||||
"proposalDisplay.requestedBsqTextField must not be null");
|
||||
checkNotNull(proposalDisplay.bsqAddressTextField,
|
||||
"proposalDisplay.bsqAddressTextField must not be null");
|
||||
return daoFacade.getCompensationProposalWithTransaction(proposalDisplay.nameTextField.getText(),
|
||||
proposalDisplay.linkInputTextField.getText(),
|
||||
bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText()),
|
||||
proposalDisplay.bsqAddressTextField.getText());
|
||||
bsqFormatter.parseToCoin(proposalDisplay.requestedBsqTextField.getText()));
|
||||
case CHANGE_PARAM:
|
||||
checkNotNull(proposalDisplay.paramComboBox,
|
||||
"proposalDisplay.paramComboBox must no tbe null");
|
||||
|
@ -324,7 +321,7 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> implements
|
|||
|
||||
private void addProposalDisplay() {
|
||||
if (selectedProposalType != null) {
|
||||
proposalDisplay = new ProposalDisplay(root, bsqFormatter, bsqWalletService, daoFacade);
|
||||
proposalDisplay = new ProposalDisplay(root, bsqFormatter, daoFacade);
|
||||
proposalDisplay.createAllFields(Res.get("dao.proposal.create.createNew"), alwaysVisibleGridRowIndex, Layout.GROUP_DISTANCE,
|
||||
selectedProposalType, true);
|
||||
|
||||
|
|
|
@ -17,17 +17,21 @@
|
|||
|
||||
package bisq.desktop.main.dao.governance.proposals;
|
||||
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
import bisq.core.dao.governance.ballot.Ballot;
|
||||
import bisq.core.dao.governance.ballot.vote.Vote;
|
||||
import bisq.core.dao.governance.proposal.Proposal;
|
||||
import bisq.core.dao.state.period.DaoPhase;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tooltip;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
|
@ -43,6 +47,20 @@ import javax.annotation.Nullable;
|
|||
@EqualsAndHashCode
|
||||
//TODO merge with vote result ProposalListItem
|
||||
public class ProposalsListItem {
|
||||
|
||||
enum IconButtonTypes {
|
||||
REMOVE_PROPOSAL(Res.get("dao.proposal.table.icon.tooltip.removeProposal")),
|
||||
ACCEPT(Res.get("dao.proposal.display.myVote.accepted")),
|
||||
REJECT(Res.get("dao.proposal.display.myVote.rejected")),
|
||||
IGNORE(Res.get("dao.proposal.display.myVote.ignored"));
|
||||
@Getter
|
||||
private String title;
|
||||
|
||||
IconButtonTypes(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final Proposal proposal;
|
||||
private final DaoFacade daoFacade;
|
||||
|
@ -53,7 +71,7 @@ public class ProposalsListItem {
|
|||
private Ballot ballot;
|
||||
|
||||
@Getter
|
||||
private Label icon;
|
||||
private Button iconButton;
|
||||
|
||||
private ChangeListener<DaoPhase.Phase> phaseChangeListener;
|
||||
|
||||
|
@ -101,33 +119,61 @@ public class ProposalsListItem {
|
|||
|
||||
public void onPhaseChanged(DaoPhase.Phase phase) {
|
||||
//noinspection IfCanBeSwitch
|
||||
Label icon;
|
||||
if (phase == DaoPhase.Phase.PROPOSAL) {
|
||||
icon = AwesomeDude.createIconLabel(AwesomeIcon.FILE_TEXT);
|
||||
icon = FormBuilder.getIcon(AwesomeIcon.TRASH);
|
||||
|
||||
icon.getStyleClass().addAll("icon", "dao-remove-proposal-icon");
|
||||
iconButton = new Button("", icon);
|
||||
boolean isMyProposal = daoFacade.isMyProposal(proposal);
|
||||
icon.setVisible(isMyProposal);
|
||||
icon.setManaged(isMyProposal);
|
||||
} else if (icon != null) {
|
||||
icon.setVisible(true);
|
||||
icon.setManaged(true);
|
||||
if (isMyProposal)
|
||||
iconButton.setUserData(IconButtonTypes.REMOVE_PROPOSAL);
|
||||
iconButton.setVisible(isMyProposal);
|
||||
iconButton.setManaged(isMyProposal);
|
||||
iconButton.getStyleClass().add("hidden-icon-button");
|
||||
iconButton.setTooltip(new Tooltip(Res.get("dao.proposal.table.icon.tooltip.removeProposal")));
|
||||
} else if (iconButton != null) {
|
||||
iconButton.setVisible(true);
|
||||
iconButton.setManaged(true);
|
||||
}
|
||||
|
||||
// ballot
|
||||
if (ballot != null) {
|
||||
final Vote vote = ballot.getVote();
|
||||
Vote vote = ballot.getVote();
|
||||
|
||||
if (vote != null) {
|
||||
if ((vote).isAccepted()) {
|
||||
icon = AwesomeDude.createIconLabel(AwesomeIcon.THUMBS_UP);
|
||||
icon = FormBuilder.getIcon(AwesomeIcon.THUMBS_UP);
|
||||
icon.getStyleClass().addAll("icon", "dao-accepted-icon");
|
||||
iconButton = new Button("", icon);
|
||||
iconButton.setUserData(IconButtonTypes.ACCEPT);
|
||||
} else {
|
||||
icon = AwesomeDude.createIconLabel(AwesomeIcon.THUMBS_DOWN);
|
||||
icon = FormBuilder.getIcon(AwesomeIcon.THUMBS_DOWN);
|
||||
icon.getStyleClass().addAll("icon", "dao-rejected-icon");
|
||||
iconButton = new Button("", icon);
|
||||
iconButton.setUserData(IconButtonTypes.REJECT);
|
||||
}
|
||||
} else {
|
||||
icon = AwesomeDude.createIconLabel(AwesomeIcon.MINUS);
|
||||
icon = FormBuilder.getIcon(AwesomeIcon.MINUS);
|
||||
icon.getStyleClass().addAll("icon", "dao-ignored-icon");
|
||||
iconButton = new Button("", icon);
|
||||
iconButton.setUserData(IconButtonTypes.IGNORE);
|
||||
}
|
||||
icon.layout();
|
||||
iconButton.setTooltip(new Tooltip(Res.get("dao.proposal.table.icon.tooltip.changeVote",
|
||||
((IconButtonTypes) iconButton.getUserData()).getTitle(),
|
||||
getNext(((IconButtonTypes) iconButton.getUserData()))
|
||||
)));
|
||||
iconButton.getStyleClass().add("hidden-icon-button");
|
||||
iconButton.layout();
|
||||
}
|
||||
}
|
||||
|
||||
private String getNext(IconButtonTypes iconButtonTypes) {
|
||||
if (iconButtonTypes == IconButtonTypes.ACCEPT)
|
||||
return IconButtonTypes.REJECT.getTitle();
|
||||
else if (iconButtonTypes == IconButtonTypes.REJECT)
|
||||
return IconButtonTypes.IGNORE.getTitle();
|
||||
else
|
||||
return IconButtonTypes.ACCEPT.getTitle();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
private ListChangeListener<Ballot> ballotListChangeListener;
|
||||
private ChangeListener<String> stakeListener;
|
||||
private Subscription selectedProposalSubscription, phaseSubscription;
|
||||
private boolean areVoteButtonsVisible;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -306,7 +307,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
onSelectProposal(null);
|
||||
}
|
||||
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 33, 28, 2, 4);
|
||||
GUIUtil.setFitToRowsForTableView(tableView, 37, 28, 2, 4);
|
||||
tableView.layout();
|
||||
root.layout();
|
||||
}
|
||||
|
@ -346,7 +347,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
ignoreButton = tuple.third;
|
||||
acceptButton.setOnAction(event -> onAccept());
|
||||
rejectButton.setOnAction(event -> onReject());
|
||||
ignoreButton.setOnAction(event -> onCancelVote());
|
||||
ignoreButton.setOnAction(event -> onIgnore());
|
||||
|
||||
voteButtons.clear();
|
||||
voteButtons.add(voteButton);
|
||||
|
@ -405,13 +406,18 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
|
||||
private void onRemoveProposal() {
|
||||
if (daoFacade.phaseProperty().get() == DaoPhase.Phase.PROPOSAL) {
|
||||
final Proposal proposal = selectedItem.getProposal();
|
||||
if (daoFacade.removeMyProposal(proposal)) {
|
||||
hideProposalDisplay();
|
||||
} else {
|
||||
new Popup<>().warning(Res.get("dao.proposal.active.remove.failed")).show();
|
||||
}
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
Proposal proposal = selectedItem.getProposal();
|
||||
new Popup<>().warning(Res.get("dao.proposal.active.remove.confirm"))
|
||||
.actionButtonText(Res.get("dao.proposal.active.remove.doRemove"))
|
||||
.onAction(() -> {
|
||||
if (daoFacade.removeMyProposal(proposal)) {
|
||||
hideProposalDisplay();
|
||||
} else {
|
||||
new Popup<>().warning(Res.get("dao.proposal.active.remove.failed")).show();
|
||||
}
|
||||
tableView.getSelectionModel().clearSelection();
|
||||
})
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -466,7 +472,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
updateStateAfterVote();
|
||||
}
|
||||
|
||||
private void onCancelVote() {
|
||||
private void onIgnore() {
|
||||
daoFacade.setVote(getBallotListItem().getBallot(), null);
|
||||
proposalDisplay.applyBallot(getBallotListItem().getBallot());
|
||||
updateStateAfterVote();
|
||||
|
@ -543,15 +549,17 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
stakeInputTextField.setMouseTransparent(true);
|
||||
}
|
||||
|
||||
boolean showVoteFields = isBlindVotePhaseButNotLastBlock || hasAlreadyVoted;
|
||||
boolean hasProposals = !daoFacade.getActiveOrMyUnconfirmedProposals().isEmpty();
|
||||
boolean showVoteFields = (isBlindVotePhaseButNotLastBlock && hasProposals) || hasAlreadyVoted;
|
||||
|
||||
voteFields.forEach(node -> {
|
||||
node.setVisible(showVoteFields);
|
||||
node.setManaged(showVoteFields);
|
||||
});
|
||||
areVoteButtonsVisible = hasProposals && isBlindVotePhaseButNotLastBlock && !hasAlreadyVoted;
|
||||
voteButtons.forEach(button -> {
|
||||
button.setVisible(isBlindVotePhaseButNotLastBlock && !hasAlreadyVoted);
|
||||
button.setManaged(isBlindVotePhaseButNotLastBlock && !hasAlreadyVoted);
|
||||
button.setVisible(areVoteButtonsVisible);
|
||||
button.setManaged(areVoteButtonsVisible);
|
||||
});
|
||||
|
||||
blindVoteTxIdTextField.setup("");
|
||||
|
@ -643,7 +651,7 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
}
|
||||
|
||||
private void createEmptyProposalDisplay() {
|
||||
proposalDisplay = new ProposalDisplay(proposalDisplayGridPane, bsqFormatter, bsqWalletService, daoFacade);
|
||||
proposalDisplay = new ProposalDisplay(proposalDisplayGridPane, bsqFormatter, daoFacade);
|
||||
proposalDisplayView = proposalDisplay.getView();
|
||||
GridPane.setMargin(proposalDisplayView, new Insets(0, -10, 0, -10));
|
||||
GridPane.setRowIndex(proposalDisplayView, ++gridRow);
|
||||
|
@ -819,32 +827,51 @@ public class ProposalsView extends ActivatableView<GridPane, Void> implements Bs
|
|||
|
||||
|
||||
column = new TableColumn<>();
|
||||
column.setMinWidth(40);
|
||||
column.setMinWidth(50);
|
||||
column.setMaxWidth(column.getMinWidth());
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<TableColumn<ProposalsListItem, ProposalsListItem>,
|
||||
TableCell<ProposalsListItem, ProposalsListItem>>() {
|
||||
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<ProposalsListItem, ProposalsListItem> call(TableColumn<ProposalsListItem,
|
||||
ProposalsListItem> column) {
|
||||
return new TableCell<ProposalsListItem, ProposalsListItem>() {
|
||||
Label icon;
|
||||
return new TableCell<>() {
|
||||
Button iconButton;
|
||||
|
||||
@Override
|
||||
public void updateItem(final ProposalsListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
if (item != null && !empty) {
|
||||
if (icon == null) {
|
||||
if (iconButton == null) {
|
||||
item.onPhaseChanged(currentPhase);
|
||||
icon = item.getIcon();
|
||||
setGraphic(icon);
|
||||
iconButton = item.getIconButton();
|
||||
log.error("1 areVoteButtonsVisible " + areVoteButtonsVisible);
|
||||
if (iconButton != null) {
|
||||
iconButton.setOnAction(e -> {
|
||||
log.error("2 areVoteButtonsVisible " + areVoteButtonsVisible);
|
||||
if (areVoteButtonsVisible) {
|
||||
onSelectProposal(item);
|
||||
if (iconButton.getUserData() == ProposalsListItem.IconButtonTypes.REMOVE_PROPOSAL)
|
||||
onRemoveProposal();
|
||||
else if (iconButton.getUserData() == ProposalsListItem.IconButtonTypes.ACCEPT)
|
||||
onReject();
|
||||
else if (iconButton.getUserData() == ProposalsListItem.IconButtonTypes.REJECT)
|
||||
onIgnore();
|
||||
else if (iconButton.getUserData() == ProposalsListItem.IconButtonTypes.IGNORE)
|
||||
onAccept();
|
||||
}
|
||||
});
|
||||
|
||||
if (!areVoteButtonsVisible && iconButton.getUserData() != ProposalsListItem.IconButtonTypes.REMOVE_PROPOSAL) {
|
||||
iconButton.setMouseTransparent(true);
|
||||
iconButton.setStyle("-fx-cursor: default;");
|
||||
}
|
||||
setGraphic(iconButton);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (icon != null)
|
||||
icon = null;
|
||||
if (iconButton != null)
|
||||
iconButton = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
|
||||
package bisq.desktop.main.dao.governance.result;
|
||||
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
|
||||
import bisq.core.dao.governance.ballot.Ballot;
|
||||
import bisq.core.dao.governance.ballot.vote.Vote;
|
||||
import bisq.core.dao.governance.proposal.Proposal;
|
||||
|
@ -33,7 +35,6 @@ import bisq.core.util.BsqFormatter;
|
|||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
|
@ -66,15 +67,15 @@ public class ProposalListItem {
|
|||
Label myVoteIcon;
|
||||
if (vote != null) {
|
||||
if ((vote).isAccepted()) {
|
||||
myVoteIcon = AwesomeDude.createIconLabel(AwesomeIcon.THUMBS_UP);
|
||||
myVoteIcon.getStyleClass().addAll("icon", "dao-accepted-icon");
|
||||
myVoteIcon = FormBuilder.getIcon(AwesomeIcon.THUMBS_UP);
|
||||
myVoteIcon.getStyleClass().add("dao-accepted-icon");
|
||||
} else {
|
||||
myVoteIcon = AwesomeDude.createIconLabel(AwesomeIcon.THUMBS_DOWN);
|
||||
myVoteIcon.getStyleClass().addAll("icon", "dao-rejected-icon");
|
||||
myVoteIcon = FormBuilder.getIcon(AwesomeIcon.THUMBS_DOWN);
|
||||
myVoteIcon.getStyleClass().add("dao-rejected-icon");
|
||||
}
|
||||
} else {
|
||||
myVoteIcon = AwesomeDude.createIconLabel(AwesomeIcon.MINUS);
|
||||
myVoteIcon.getStyleClass().addAll("icon", "dao-ignored-icon");
|
||||
myVoteIcon = FormBuilder.getIcon(AwesomeIcon.MINUS);
|
||||
myVoteIcon.getStyleClass().add("dao-ignored-icon");
|
||||
}
|
||||
return myVoteIcon;
|
||||
}
|
||||
|
|
|
@ -347,7 +347,7 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
|
||||
private void createProposalDisplay(EvaluatedProposal evaluatedProposal, Ballot ballot) {
|
||||
Proposal proposal = evaluatedProposal.getProposal();
|
||||
ProposalDisplay proposalDisplay = new ProposalDisplay(new GridPane(), bsqFormatter, bsqWalletService, daoFacade);
|
||||
ProposalDisplay proposalDisplay = new ProposalDisplay(new GridPane(), bsqFormatter, daoFacade);
|
||||
|
||||
ScrollPane proposalDisplayView = proposalDisplay.getView();
|
||||
GridPane.setMargin(proposalDisplayView, new Insets(0, -10, -15, -10));
|
||||
|
@ -851,74 +851,6 @@ public class VoteResultView extends ActivatableView<GridPane, Void> implements D
|
|||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.blindVoteTxId"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(130);
|
||||
column.setMaxWidth(column.getMinWidth());
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(TableColumn<VoteListItem,
|
||||
VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
//noinspection Duplicates
|
||||
if (item != null && !empty) {
|
||||
String blindVoteTxId = item.getBlindVoteTxId();
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(blindVoteTxId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(item.getBlindVoteTxId()));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", blindVoteTxId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (hyperlinkWithIcon != null)
|
||||
hyperlinkWithIcon.setOnAction(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
|
||||
column = new AutoTooltipTableColumn<>(Res.get("dao.results.votes.table.header.voteRevealTxId"));
|
||||
column.setSortable(false);
|
||||
column.setMinWidth(140);
|
||||
column.setMaxWidth(column.getMinWidth());
|
||||
column.setCellValueFactory((item) -> new ReadOnlyObjectWrapper<>(item.getValue()));
|
||||
column.setCellFactory(new Callback<>() {
|
||||
@Override
|
||||
public TableCell<VoteListItem, VoteListItem> call(TableColumn<VoteListItem,
|
||||
VoteListItem> column) {
|
||||
return new TableCell<>() {
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
|
||||
@Override
|
||||
public void updateItem(final VoteListItem item, boolean empty) {
|
||||
super.updateItem(item, empty);
|
||||
|
||||
//noinspection Duplicates
|
||||
if (item != null && !empty) {
|
||||
String voteRevealTxId = item.getVoteRevealTxId();
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(voteRevealTxId, AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setOnAction(event -> openTxInBlockExplorer(item.getVoteRevealTxId()));
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", voteRevealTxId)));
|
||||
setGraphic(hyperlinkWithIcon);
|
||||
} else {
|
||||
setGraphic(null);
|
||||
if (hyperlinkWithIcon != null)
|
||||
hyperlinkWithIcon.setOnAction(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
votesTableView.getColumns().add(column);
|
||||
}
|
||||
|
||||
private void openTxInBlockExplorer(String txId) {
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
package bisq.desktop.main.dao.wallet;
|
||||
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.btc.listeners.BsqBalanceListener;
|
||||
|
@ -24,10 +25,13 @@ import bisq.core.btc.wallet.BsqWalletService;
|
|||
import bisq.core.locale.Res;
|
||||
import bisq.core.util.BsqFormatter;
|
||||
|
||||
import bisq.common.util.Tuple2;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
|
@ -47,6 +51,8 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
|
||||
// Displaying bond dashboard info
|
||||
private TextField lockupAmountTextField, unlockingAmountTextField;
|
||||
private TitledGroupBg titledGroupBg;
|
||||
private Label availableNonBsqBalanceLabel;
|
||||
|
||||
@Inject
|
||||
private BsqBalanceUtil(BsqWalletService bsqWalletService,
|
||||
|
@ -56,16 +62,12 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
}
|
||||
|
||||
public int addGroup(GridPane gridPane, int gridRow) {
|
||||
addTitledGroupBg(gridPane, gridRow, 6, Res.get("shared.balance"));
|
||||
titledGroupBg = addTitledGroupBg(gridPane, gridRow, 5, Res.get("dao.wallet.dashboard.myBalance"));
|
||||
availableBalanceTextField = addLabelTextField(gridPane, gridRow,
|
||||
Res.getWithCol("dao.availableBsqBalance"),
|
||||
Layout.FIRST_ROW_DISTANCE).second;
|
||||
availableBalanceTextField.setMouseTransparent(false);
|
||||
|
||||
availableNonBsqBalanceTextField = addLabelTextField(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.availableNonBsqBalance")).second;
|
||||
availableNonBsqBalanceTextField.setMouseTransparent(false);
|
||||
|
||||
unverifiedBalanceTextField = addLabelTextField(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.unverifiedBsqBalance")).second;
|
||||
unverifiedBalanceTextField.setMouseTransparent(false);
|
||||
|
@ -84,6 +86,14 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
Res.getWithCol("dao.totalBsqBalance")).second;
|
||||
totalBalanceTextField.setMouseTransparent(false);
|
||||
|
||||
Tuple2<Label, TextField> tuple2 = addLabelTextField(gridPane, ++gridRow,
|
||||
Res.getWithCol("dao.availableNonBsqBalance"));
|
||||
availableNonBsqBalanceLabel = tuple2.first;
|
||||
availableNonBsqBalanceTextField = tuple2.second;
|
||||
availableNonBsqBalanceTextField.setMouseTransparent(false);
|
||||
availableNonBsqBalanceTextField.setVisible(false);
|
||||
availableNonBsqBalanceTextField.setManaged(false);
|
||||
|
||||
return gridRow;
|
||||
}
|
||||
|
||||
|
@ -125,8 +135,12 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
Coin lockedForVotingBalance,
|
||||
Coin lockupBondsBalance,
|
||||
Coin unlockingBondsBalance) {
|
||||
|
||||
boolean isNonBsqBalanceAvailable = availableNonBsqBalance.value > 0;
|
||||
int rowSpan = isNonBsqBalanceAvailable ? 6 : 5;
|
||||
GridPane.setRowSpan(titledGroupBg, rowSpan);
|
||||
|
||||
availableBalanceTextField.setText(bsqFormatter.formatCoinWithCode(availableBalance));
|
||||
availableNonBsqBalanceTextField.setText(bsqFormatter.formatBtcSatoshi(availableNonBsqBalance.value));
|
||||
unverifiedBalanceTextField.setText(bsqFormatter.formatCoinWithCode(unverifiedBalance));
|
||||
lockedForVoteBalanceTextField.setText(bsqFormatter.formatCoinWithCode(lockedForVotingBalance));
|
||||
lockedInBondsBalanceTextField.setText(bsqFormatter.formatCoinWithCode(
|
||||
|
@ -137,6 +151,12 @@ public class BsqBalanceUtil implements BsqBalanceListener {
|
|||
unlockingAmountTextField.setText(bsqFormatter.formatCoinWithCode(unlockingBondsBalance));
|
||||
}
|
||||
|
||||
availableNonBsqBalanceLabel.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceLabel.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setVisible(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setManaged(isNonBsqBalanceAvailable);
|
||||
availableNonBsqBalanceTextField.setText(bsqFormatter.formatBTCWithCode(availableNonBsqBalance.value));
|
||||
|
||||
final Coin total = availableBalance
|
||||
.add(unverifiedBalance)
|
||||
.add(lockedForVotingBalance)
|
||||
|
|
|
@ -19,10 +19,8 @@ package bisq.desktop.main.dao.wallet.dashboard;
|
|||
|
||||
import bisq.desktop.common.view.ActivatableView;
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.main.dao.wallet.BsqBalanceUtil;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.dao.DaoFacade;
|
||||
|
@ -42,17 +40,13 @@ import org.bitcoinj.core.Coin;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.control.Tooltip;
|
||||
import javafx.scene.layout.GridPane;
|
||||
|
||||
import javafx.geometry.Insets;
|
||||
|
||||
import javafx.beans.value.ChangeListener;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.addLabelHyperlinkWithIcon;
|
||||
import static bisq.desktop.util.FormBuilder.addLabelTextField;
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
|
||||
|
@ -68,9 +62,8 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
private int gridRow = 0;
|
||||
private TextField genesisIssueAmountTextField, compRequestIssueAmountTextField, availableAmountTextField,
|
||||
burntAmountTextField, totalLockedUpAmountTextField, totalUnlockingAmountTextField,
|
||||
totalUnlockedAmountTextField, allTxTextField,
|
||||
burntTxTextField,
|
||||
utxoTextField, priceTextField, marketCapTextField;
|
||||
totalUnlockedAmountTextField, allTxTextField, burntTxTextField, utxoTextField, issuanceTxTextField,
|
||||
priceTextField, marketCapTextField;
|
||||
private ChangeListener<Number> priceChangeListener;
|
||||
private HyperlinkWithIcon hyperlinkWithIcon;
|
||||
|
||||
|
@ -96,34 +89,34 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
public void initialize() {
|
||||
gridRow = bsqBalanceUtil.addGroup(root, gridRow);
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 14, Res.get("dao.wallet.dashboard.statistics"), Layout.GROUP_DISTANCE);
|
||||
addTitledGroupBg(root, ++gridRow, 4, Res.get("dao.wallet.dashboard.distribution"), Layout.GROUP_DISTANCE);
|
||||
|
||||
addLabelTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisBlockHeight"),
|
||||
String.valueOf(daoFacade.getGenesisBlockHeight()), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
|
||||
Label label = new AutoTooltipLabel(Res.get("dao.wallet.dashboard.genesisTxId"));
|
||||
GridPane.setRowIndex(label, ++gridRow);
|
||||
root.getChildren().add(label);
|
||||
hyperlinkWithIcon = new HyperlinkWithIcon(daoFacade.getGenesisTxId(), AwesomeIcon.EXTERNAL_LINK);
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", daoFacade.getGenesisTxId())));
|
||||
GridPane.setRowIndex(hyperlinkWithIcon, gridRow);
|
||||
GridPane.setColumnIndex(hyperlinkWithIcon, 1);
|
||||
GridPane.setMargin(hyperlinkWithIcon, new Insets(0, 0, 0, -4));
|
||||
root.getChildren().add(hyperlinkWithIcon);
|
||||
|
||||
genesisIssueAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount")).second;
|
||||
genesisIssueAmountTextField = addLabelTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisIssueAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
compRequestIssueAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.compRequestIssueAmount")).second;
|
||||
availableAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
||||
burntAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntAmount")).second;
|
||||
totalLockedUpAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.totalLockedUpAmount")).second;
|
||||
availableAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.availableAmount")).second;
|
||||
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 3, Res.get("dao.wallet.dashboard.locked"), Layout.GROUP_DISTANCE);
|
||||
totalLockedUpAmountTextField = addLabelTextField(root, gridRow, Res.get("dao.wallet.dashboard.totalLockedUpAmount"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
totalUnlockingAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.totalUnlockingAmount")).second;
|
||||
totalUnlockedAmountTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.totalUnlockedAmount")).second;
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 2, Res.get("dao.wallet.dashboard.market"), Layout.GROUP_DISTANCE);
|
||||
priceTextField = addLabelTextField(root, gridRow, Res.get("dao.wallet.dashboard.price"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
marketCapTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
||||
|
||||
|
||||
addTitledGroupBg(root, ++gridRow, 6, Res.get("dao.wallet.dashboard.txDetails"), Layout.GROUP_DISTANCE);
|
||||
addLabelTextField(root, gridRow, Res.get("dao.wallet.dashboard.genesisBlockHeight"),
|
||||
String.valueOf(daoFacade.getGenesisBlockHeight()), Layout.FIRST_ROW_AND_GROUP_DISTANCE);
|
||||
hyperlinkWithIcon = addLabelHyperlinkWithIcon(root, ++gridRow, Res.get("dao.wallet.dashboard.genesisTxId"),
|
||||
daoFacade.getGenesisTxId(), preferences.getBsqBlockChainExplorer().txUrl + daoFacade.getGenesisTxId()).second;
|
||||
hyperlinkWithIcon.setTooltip(new Tooltip(Res.get("tooltip.openBlockchainForTx", daoFacade.getGenesisTxId())));
|
||||
allTxTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.allTx")).second;
|
||||
utxoTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.utxo")).second;
|
||||
issuanceTxTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.issuanceTx")).second;
|
||||
burntTxTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.burntTx")).second;
|
||||
priceTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.price")).second;
|
||||
marketCapTextField = addLabelTextField(root, ++gridRow, Res.get("dao.wallet.dashboard.marketCap")).second;
|
||||
|
||||
priceChangeListener = (observable, oldValue, newValue) -> updatePrice();
|
||||
}
|
||||
|
@ -135,8 +128,6 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
daoFacade.addBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().addListener(priceChangeListener);
|
||||
|
||||
hyperlinkWithIcon.setOnAction(event -> GUIUtil.openWebPage(preferences.getBsqBlockChainExplorer().txUrl + daoFacade.getGenesisTxId()));
|
||||
|
||||
updateWithBsqBlockChainData();
|
||||
updatePrice();
|
||||
}
|
||||
|
@ -146,7 +137,6 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
bsqBalanceUtil.deactivate();
|
||||
daoFacade.removeBsqStateListener(this);
|
||||
priceFeedService.updateCounterProperty().removeListener(priceChangeListener);
|
||||
hyperlinkWithIcon.setOnAction(null);
|
||||
}
|
||||
|
||||
|
||||
|
@ -186,12 +176,13 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
Coin availableAmount = issuedAmountFromGenesis.add(issuedAmountFromCompRequests).subtract(burntFee);
|
||||
|
||||
availableAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(availableAmount));
|
||||
burntAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
||||
burntAmountTextField.setText("-" + bsqFormatter.formatAmountWithGroupSeparatorAndCode(burntFee));
|
||||
totalLockedUpAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalLockedUpAmount));
|
||||
totalUnlockingAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockingAmount));
|
||||
totalUnlockedAmountTextField.setText(bsqFormatter.formatAmountWithGroupSeparatorAndCode(totalUnlockedAmount));
|
||||
allTxTextField.setText(String.valueOf(daoFacade.getTxs().size()));
|
||||
utxoTextField.setText(String.valueOf(daoFacade.getUnspentTxOutputs().size()));
|
||||
issuanceTxTextField.setText(String.valueOf(daoFacade.getIssuanceSet().size()));
|
||||
burntTxTextField.setText(String.valueOf(daoFacade.getFeeTxs().size()));
|
||||
}
|
||||
|
||||
|
@ -203,6 +194,9 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
|
|||
priceTextField.setText(bsqFormatter.formatPrice(Price.valueOf("BSQ", bsqPrice)) + " BSQ/BTC");
|
||||
|
||||
marketCapTextField.setText(bsqFormatter.formatMarketCap(bsqMarketPrice, priceFeedService.getMarketPrice("USD"), issuedAmount));
|
||||
} else {
|
||||
priceTextField.setText(Res.get("shared.na"));
|
||||
marketCapTextField.setText(Res.get("shared.na"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public class BsqReceiveView extends ActivatableView<GridPane, Void> {
|
|||
|
||||
addTitledGroupBg(root, ++gridRow, 1, Res.get("dao.wallet.receive.fundYourWallet"), Layout.GROUP_DISTANCE);
|
||||
|
||||
addressTextField = addLabelBsqAddressTextField(root, gridRow, Res.getWithCol("shared.address"),
|
||||
addressTextField = addLabelBsqAddressTextField(root, gridRow, Res.getWithCol("dao.wallet.receive.bsqAddress"),
|
||||
Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
addressTextField.setPaymentLabel(paymentLabelString);
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ public class BsqSendView extends ActivatableView<GridPane, Void> implements BsqB
|
|||
receiversAddressInputTextField.setValidator(bsqAddressValidator);
|
||||
|
||||
amountInputTextField = addLabelInputTextField(root, ++gridRow, Res.get("dao.wallet.send.amount")).second;
|
||||
amountInputTextField.setPromptText(Res.get("dao.wallet.send.setAmount", bsqFormatter.formatCoin(Restrictions.getMinNonDustOutput())));
|
||||
amountInputTextField.setPromptText(Res.get("dao.wallet.send.setAmount", bsqFormatter.formatCoinWithCode(Restrictions.getMinNonDustOutput())));
|
||||
amountInputTextField.setValidator(bsqValidator);
|
||||
|
||||
focusOutListener = (observable, oldValue, newValue) -> {
|
||||
|
@ -290,16 +290,16 @@ public class BsqSendView extends ActivatableView<GridPane, Void> implements BsqB
|
|||
Tuple2<Label, InputTextField> tuple2 = addLabelInputTextField(root, ++gridRow, Res.get("dao.wallet.send.btcAmount"));
|
||||
btcAmountLabel = tuple2.first;
|
||||
btcAmountInputTextField = tuple2.second;
|
||||
btcAmountInputTextField.setPromptText(Res.get("dao.wallet.send.setBtcAmount", Restrictions.getMinNonDustOutput().value));
|
||||
btcAmountInputTextField.setPromptText(Res.get("dao.wallet.send.setBtcAmount",
|
||||
bsqFormatter.formatBTCWithCode(Restrictions.getMinNonDustOutput().value)));
|
||||
btcAmountInputTextField.setValidator(btcValidator);
|
||||
|
||||
sendBtcButton = addButtonAfterGroup(root, ++gridRow, Res.get("dao.wallet.send.sendBtc"));
|
||||
|
||||
sendBtcButton.setOnAction((event) -> {
|
||||
// TODO break up in methods
|
||||
if (GUIUtil.isReadyForTxBroadcast(p2PService, walletsSetup)) {
|
||||
String receiversAddressString = receiversBtcAddressInputTextField.getText();
|
||||
Coin receiverAmount = bsqFormatter.parseSatoshiToBtc(btcAmountInputTextField.getText());
|
||||
Coin receiverAmount = bsqFormatter.parseToBTC(btcAmountInputTextField.getText());
|
||||
try {
|
||||
Transaction preparedSendTx = bsqWalletService.getPreparedSendBtcTx(receiversAddressString, receiverAmount);
|
||||
Transaction txWithBtcFee = btcWalletService.completePreparedSendBsqTx(preparedSendTx, true);
|
||||
|
|
|
@ -44,7 +44,6 @@ import org.bitcoinj.core.Transaction;
|
|||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import de.jensd.fx.fontawesome.AwesomeDude;
|
||||
import de.jensd.fx.fontawesome.AwesomeIcon;
|
||||
|
||||
import javafx.scene.control.Label;
|
||||
|
@ -569,7 +568,7 @@ public class BsqTxView extends ActivatableView<GridPane, Void> implements BsqBal
|
|||
style = "dao-tx-type-unverified-icon";
|
||||
break;
|
||||
}
|
||||
Label label = AwesomeDude.createIconLabel(awesomeIcon);
|
||||
Label label = FormBuilder.getIcon(awesomeIcon);
|
||||
label.getStyleClass().addAll("icon", style);
|
||||
label.setTooltip(new Tooltip(toolTipText));
|
||||
if (doRotate)
|
||||
|
|
|
@ -156,7 +156,7 @@ public class EmptyWalletWindow extends Overlay<EmptyWalletWindow> {
|
|||
addressInputTextField = addLabelInputTextField(gridPane, ++rowIndex, Res.get("emptyWalletWindow.address")).second;
|
||||
} else {
|
||||
addLabelTextField(gridPane, ++rowIndex, Res.get("emptyWalletWindow.bsq.btcBalance"),
|
||||
bsqFormatter.formatBtcSatoshi(bsqWalletService.getAvailableNonBsqBalance().value), 10);
|
||||
bsqFormatter.formatBTCWithCode(bsqWalletService.getAvailableNonBsqBalance().value), 10);
|
||||
}
|
||||
closeButton = new AutoTooltipButton(Res.get("shared.cancel"));
|
||||
closeButton.setOnAction(e -> {
|
||||
|
|
|
@ -23,9 +23,11 @@ import bisq.desktop.common.view.FxmlView;
|
|||
import bisq.desktop.components.AutoTooltipButton;
|
||||
import bisq.desktop.components.AutoTooltipLabel;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.PasswordTextField;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.FormBuilder;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.ImageUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
|
@ -99,7 +101,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
|||
private CheckBox useAnimationsCheckBox, avoidStandbyModeCheckBox,
|
||||
showOwnOffersInOfferBook, sortMarketCurrenciesNumericallyCheckBox, useCustomFeeCheckbox;
|
||||
private int gridRow = 0;
|
||||
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField;
|
||||
private InputTextField transactionFeeInputTextField, ignoreTradersListInputTextField, referralIdInputTextField, rpcUserTextField;
|
||||
private CheckBox isDaoFullNodeCheckBox;
|
||||
private PasswordTextField rpcPwTextField;
|
||||
private TitledGroupBg daoOptionsTitledGroupBg;
|
||||
private Label rpcUserLabel, rpcPwLabel;
|
||||
|
||||
private ChangeListener<Boolean> transactionFeeFocusedListener;
|
||||
private final Preferences preferences;
|
||||
private final FeeService feeService;
|
||||
|
@ -124,11 +131,12 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
|||
private ObservableList<CryptoCurrency> allCryptoCurrencies;
|
||||
private ObservableList<TradeCurrency> tradeCurrencies;
|
||||
private InputTextField deviationInputTextField;
|
||||
private ChangeListener<String> deviationListener, ignoreTradersListListener, referralIdListener;
|
||||
private ChangeListener<String> deviationListener, ignoreTradersListListener, referralIdListener, rpcUserListener, rpcPwListener;
|
||||
private ChangeListener<Boolean> deviationFocusedListener;
|
||||
private ChangeListener<Boolean> useCustomFeeCheckboxListener;
|
||||
private ChangeListener<Number> transactionFeeChangeListener;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Constructor, initialisation
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -501,12 +509,36 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
|||
}
|
||||
|
||||
private void initializeDaoOptions() {
|
||||
TitledGroupBg titledGroupBg = addTitledGroupBg(root, ++gridRow, 1, Res.get("setting.preferences.daoOptions"), Layout.GROUP_DISTANCE);
|
||||
GridPane.setColumnSpan(titledGroupBg, 4);
|
||||
daoOptionsTitledGroupBg = addTitledGroupBg(root, ++gridRow, 2, Res.get("setting.preferences.daoOptions"), Layout.GROUP_DISTANCE);
|
||||
GridPane.setColumnSpan(daoOptionsTitledGroupBg, 4);
|
||||
resyncDaoButton = addLabelButton(root, gridRow, Res.get("setting.preferences.dao.resync.label"),
|
||||
Res.get("setting.preferences.dao.resync.button"), Layout.FIRST_ROW_AND_GROUP_DISTANCE).second;
|
||||
|
||||
isDaoFullNodeCheckBox = addLabelCheckBox(root, ++gridRow, Res.getWithCol("setting.preferences.dao.isDaoFullNode")).second;
|
||||
Tuple2<Label, InputTextField> tuple = addLabelInputTextField(root, ++gridRow, Res.getWithCol("setting.preferences.dao.rpcUser"));
|
||||
rpcUserLabel = tuple.first;
|
||||
rpcUserLabel.setVisible(false);
|
||||
rpcUserLabel.setManaged(false);
|
||||
rpcUserTextField = tuple.second;
|
||||
rpcUserTextField.setVisible(false);
|
||||
rpcUserTextField.setManaged(false);
|
||||
Tuple2<Label, PasswordTextField> tuple2 = addLabelPasswordTextField(root, ++gridRow, Res.getWithCol("setting.preferences.dao.rpcPw"));
|
||||
rpcPwLabel = tuple2.first;
|
||||
rpcPwLabel.setVisible(false);
|
||||
rpcPwLabel.setManaged(false);
|
||||
rpcPwTextField = tuple2.second;
|
||||
rpcPwTextField.setVisible(false);
|
||||
rpcPwTextField.setManaged(false);
|
||||
|
||||
rpcUserListener = (observable, oldValue, newValue) -> {
|
||||
preferences.setRpcUser(rpcUserTextField.getText());
|
||||
};
|
||||
rpcPwListener = (observable, oldValue, newValue) -> {
|
||||
preferences.setRpcPw(rpcPwTextField.getText());
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Activate
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -695,12 +727,67 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
|||
}
|
||||
|
||||
private void activateDaoPreferences() {
|
||||
boolean daoFullNode = preferences.isDaoFullNode();
|
||||
isDaoFullNodeCheckBox.setSelected(daoFullNode);
|
||||
String rpcUser = preferences.getRpcUser();
|
||||
String rpcPw = preferences.getRpcPw();
|
||||
if (daoFullNode && (rpcUser == null || rpcUser.isEmpty() || rpcPw == null || rpcPw.isEmpty())) {
|
||||
log.warn("You have full DAO node selected but have not provided the rpc username and password. We reset daoFullNode to false");
|
||||
isDaoFullNodeCheckBox.setSelected(false);
|
||||
}
|
||||
rpcUserTextField.setText(rpcUser);
|
||||
rpcPwTextField.setText(rpcPw);
|
||||
updateDaoFields();
|
||||
|
||||
resyncDaoButton.setOnAction(e -> daoFacade.resyncDao(() -> {
|
||||
new Popup<>().attention(Res.get("setting.preferences.dao.resync.popup"))
|
||||
.useShutDownButton()
|
||||
.hideCloseButton()
|
||||
.show();
|
||||
}));
|
||||
|
||||
isDaoFullNodeCheckBox.setOnAction(e -> {
|
||||
String key = "daoFullModeInfoShown";
|
||||
if (isDaoFullNodeCheckBox.isSelected() && preferences.showAgain(key)) {
|
||||
String url = "https://bisq.network/docs/dao-full-node";
|
||||
new Popup<>().backgroundInfo(Res.get("setting.preferences.dao.fullNodeInfo", url))
|
||||
.onAction(() -> {
|
||||
GUIUtil.openWebPage(url);
|
||||
})
|
||||
.actionButtonText(Res.get("setting.preferences.dao.fullNodeInfo.ok"))
|
||||
.closeButtonText(Res.get("setting.preferences.dao.fullNodeInfo.cancel"))
|
||||
.onClose(() -> UserThread.execute(() -> {
|
||||
isDaoFullNodeCheckBox.setSelected(false);
|
||||
updateDaoFields();
|
||||
}))
|
||||
.dontShowAgainId(key)
|
||||
.width(800)
|
||||
.show();
|
||||
}
|
||||
|
||||
updateDaoFields();
|
||||
});
|
||||
|
||||
rpcUserTextField.textProperty().addListener(rpcUserListener);
|
||||
rpcPwTextField.textProperty().addListener(rpcPwListener);
|
||||
}
|
||||
|
||||
private void updateDaoFields() {
|
||||
boolean isDaoFullNode = isDaoFullNodeCheckBox.isSelected();
|
||||
GridPane.setRowSpan(daoOptionsTitledGroupBg, isDaoFullNode ? 4 : 2);
|
||||
rpcUserLabel.setVisible(isDaoFullNode);
|
||||
rpcUserLabel.setManaged(isDaoFullNode);
|
||||
rpcUserTextField.setVisible(isDaoFullNode);
|
||||
rpcUserTextField.setManaged(isDaoFullNode);
|
||||
rpcPwLabel.setVisible(isDaoFullNode);
|
||||
rpcPwLabel.setManaged(isDaoFullNode);
|
||||
rpcPwTextField.setVisible(isDaoFullNode);
|
||||
rpcPwTextField.setManaged(isDaoFullNode);
|
||||
preferences.setDaoFullNode(isDaoFullNode);
|
||||
if (!isDaoFullNode) {
|
||||
rpcPwTextField.clear();
|
||||
rpcUserTextField.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void onSelectNetwork() {
|
||||
|
@ -754,5 +841,8 @@ public class PreferencesView extends ActivatableViewAndModel<GridPane, Preferenc
|
|||
|
||||
private void deactivateDaoPreferences() {
|
||||
resyncDaoButton.setOnAction(null);
|
||||
isDaoFullNodeCheckBox.setOnAction(null);
|
||||
rpcUserTextField.textProperty().removeListener(rpcUserListener);
|
||||
rpcPwTextField.textProperty().removeListener(rpcUserListener);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,10 +60,13 @@ import mockit.MockUp;
|
|||
import mockit.Tested;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
//TODO @Christoph Can you have a look why JMockit is nto working anymore in that module?
|
||||
@Ignore
|
||||
public class TradesChartsViewModelTest {
|
||||
@Tested
|
||||
TradesChartsViewModel model;
|
||||
|
|
|
@ -42,7 +42,8 @@ public class PreferenceMakers {
|
|||
lookup.valueOf(bisqEnvironment, new SameValueDonor<BisqEnvironment>(null)),
|
||||
lookup.valueOf(btcNodesFromOptions, new SameValueDonor<String>(null)),
|
||||
lookup.valueOf(useTorFlagFromOptions, new SameValueDonor<String>(null)),
|
||||
lookup.valueOf(referralID, new SameValueDonor<String>(null)));
|
||||
lookup.valueOf(referralID, new SameValueDonor<String>(null)),
|
||||
null, null, null);
|
||||
|
||||
public static final Preferences empty = make(a(Preferences));
|
||||
|
||||
|
|
|
@ -89,9 +89,9 @@ public class BSFormatterTest {
|
|||
assertEquals("1 day, 0 hours, 0 minutes", formatter.formatDurationAsWords(oneDay));
|
||||
assertEquals("2 days, 0 hours, 1 minute", formatter.formatDurationAsWords(oneDay * 2 + oneMinute));
|
||||
assertEquals("2 days, 0 hours, 2 minutes", formatter.formatDurationAsWords(oneDay * 2 + oneMinute * 2));
|
||||
assertEquals("1 hour, 0 minutes, 0 seconds", formatter.formatDurationAsWords(oneHour, true));
|
||||
assertEquals("1 hour, 0 minutes, 1 second", formatter.formatDurationAsWords(oneHour + oneSecond, true));
|
||||
assertEquals("1 hour, 0 minutes, 2 seconds", formatter.formatDurationAsWords(oneHour + oneSecond * 2, true));
|
||||
assertEquals("1 hour, 0 minutes, 0 seconds", formatter.formatDurationAsWords(oneHour, true, true));
|
||||
assertEquals("1 hour, 0 minutes, 1 second", formatter.formatDurationAsWords(oneHour + oneSecond, true, true));
|
||||
assertEquals("1 hour, 0 minutes, 2 seconds", formatter.formatDurationAsWords(oneHour + oneSecond * 2, true, true));
|
||||
assertEquals("2 days, 21 hours, 28 minutes", formatter.formatDurationAsWords(oneDay * 2 + oneHour * 21 + oneMinute * 28));
|
||||
assertEquals("", formatter.formatDurationAsWords(0));
|
||||
assertTrue(formatter.formatDurationAsWords(0).isEmpty());
|
||||
|
|
|
@ -20,11 +20,9 @@ package bisq.seednode;
|
|||
import bisq.core.app.misc.AppSetup;
|
||||
import bisq.core.app.misc.AppSetupWithP2P;
|
||||
import bisq.core.app.misc.AppSetupWithP2PAndDAO;
|
||||
import bisq.core.dao.DaoOptionKeys;
|
||||
import bisq.core.user.Preferences;
|
||||
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.name.Names;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -39,8 +37,8 @@ public class SeedNode {
|
|||
}
|
||||
|
||||
public void startApplication() {
|
||||
Boolean fullDaoNode = injector.getInstance(Key.get(Boolean.class, Names.named(DaoOptionKeys.FULL_DAO_NODE)));
|
||||
appSetup = fullDaoNode ? injector.getInstance(AppSetupWithP2PAndDAO.class) : injector.getInstance(AppSetupWithP2P.class);
|
||||
boolean isDaoFullNode = injector.getInstance(Preferences.class).isDaoFullNode();
|
||||
appSetup = isDaoFullNode ? injector.getInstance(AppSetupWithP2PAndDAO.class) : injector.getInstance(AppSetupWithP2P.class);
|
||||
appSetup.start();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue