mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-25 07:27:18 +01:00
Improve UI, logging and error handling
- Use ExceptionHandler at publishBlindVote - Add hasEnoughBsqFunds method to BlindVoteService - Show fee and confirmation popup at publish blind vote - Add GUIUtils.showBsqFeeInfoPopup to avoid code duplication - Add busyAnimation to publish blind vote button - Improve logs
This commit is contained in:
parent
4d217e682a
commit
316a305f53
7 changed files with 104 additions and 73 deletions
|
@ -23,12 +23,14 @@ import bisq.desktop.components.AutoTooltipLabel;
|
|||
import bisq.desktop.components.AutoTooltipTableColumn;
|
||||
import bisq.desktop.components.HyperlinkWithIcon;
|
||||
import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.blockchain.BsqBlockChain;
|
||||
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
|
||||
import bisq.core.dao.blockchain.vo.BsqBlock;
|
||||
import bisq.core.dao.param.DaoParamService;
|
||||
import bisq.core.dao.vote.PeriodService;
|
||||
import bisq.core.dao.vote.proposal.Proposal;
|
||||
import bisq.core.dao.vote.proposal.ProposalPayload;
|
||||
|
@ -73,8 +75,10 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
|
|||
|
||||
protected final ProposalService proposalService;
|
||||
protected final ReadableBsqBlockChain readableBsqBlockChain;
|
||||
protected final DaoParamService daoParamService;
|
||||
protected final BsqWalletService bsqWalletService;
|
||||
protected final BsqFormatter bsqFormatter;
|
||||
protected final BSFormatter btcFormatter;
|
||||
|
||||
protected final ObservableList<ProposalListItem> proposalListItems = FXCollections.observableArrayList();
|
||||
protected final SortedList<ProposalListItem> sortedList = new SortedList<>(proposalListItems);
|
||||
|
@ -101,13 +105,17 @@ public abstract class BaseProposalView extends ActivatableView<GridPane, Void> i
|
|||
protected BaseProposalView(ProposalService proposalService,
|
||||
BsqWalletService bsqWalletService,
|
||||
ReadableBsqBlockChain readableBsqBlockChain,
|
||||
DaoParamService daoParamService,
|
||||
PeriodService periodService,
|
||||
BsqFormatter bsqFormatter) {
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter) {
|
||||
this.proposalService = proposalService;
|
||||
this.bsqWalletService = bsqWalletService;
|
||||
this.readableBsqBlockChain = readableBsqBlockChain;
|
||||
this.daoParamService = daoParamService;
|
||||
this.periodService = periodService;
|
||||
this.bsqFormatter = bsqFormatter;
|
||||
this.btcFormatter = btcFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -162,7 +162,6 @@ public class ProposalListItem implements BsqBlockChain.Listener {
|
|||
//TODO
|
||||
}
|
||||
} else {
|
||||
log.error("actionButtonIconView.setVisible(false);");
|
||||
actionButtonIconView.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,36 +18,37 @@
|
|||
package bisq.desktop.main.dao.proposal.active;
|
||||
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.components.BusyAnimation;
|
||||
import bisq.desktop.components.InputTextField;
|
||||
import bisq.desktop.components.TitledGroupBg;
|
||||
import bisq.desktop.main.dao.proposal.BaseProposalView;
|
||||
import bisq.desktop.main.dao.proposal.ProposalListItem;
|
||||
import bisq.desktop.main.overlays.popups.Popup;
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.btc.exceptions.TransactionVerificationException;
|
||||
import bisq.core.btc.exceptions.WalletException;
|
||||
import bisq.core.btc.wallet.BsqBalanceListener;
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.btc.wallet.InsufficientBsqException;
|
||||
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
|
||||
import bisq.core.dao.param.DaoParamService;
|
||||
import bisq.core.dao.vote.PeriodService;
|
||||
import bisq.core.dao.vote.blindvote.BlindVoteConsensus;
|
||||
import bisq.core.dao.vote.blindvote.BlindVoteService;
|
||||
import bisq.core.dao.vote.proposal.Proposal;
|
||||
import bisq.core.dao.vote.proposal.ProposalService;
|
||||
import bisq.core.dao.vote.result.BooleanVoteResult;
|
||||
import bisq.core.locale.Res;
|
||||
|
||||
import bisq.common.UserThread;
|
||||
import bisq.common.crypto.CryptoException;
|
||||
import bisq.common.util.Tuple2;
|
||||
import bisq.common.util.Tuple3;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.InsufficientMoneyException;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
@ -62,17 +63,11 @@ import javafx.beans.property.ReadOnlyObjectWrapper;
|
|||
|
||||
import javafx.util.Callback;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static bisq.desktop.util.FormBuilder.add3ButtonsAfterGroup;
|
||||
import static bisq.desktop.util.FormBuilder.addButtonAfterGroup;
|
||||
import static bisq.desktop.util.FormBuilder.addLabelInputTextField;
|
||||
import static bisq.desktop.util.FormBuilder.addTitledGroupBg;
|
||||
import static bisq.desktop.util.FormBuilder.*;
|
||||
|
||||
@FxmlView
|
||||
public class ActiveProposalsView extends BaseProposalView implements BsqBalanceListener {
|
||||
|
@ -82,6 +77,8 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
|
|||
private Button removeButton, acceptButton, rejectButton, cancelVoteButton, voteButton;
|
||||
private InputTextField stakeInputTextField;
|
||||
private List<Node> voteViewItems = new ArrayList<>();
|
||||
private BusyAnimation voteButtonBusyAnimation;
|
||||
private Label voteButtonInfoLabel;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -94,9 +91,11 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
|
|||
BlindVoteService blindVoteService,
|
||||
BsqWalletService bsqWalletService,
|
||||
ReadableBsqBlockChain readableBsqBlockChain,
|
||||
BsqFormatter bsqFormatter) {
|
||||
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, periodService,
|
||||
bsqFormatter);
|
||||
DaoParamService daoParamService,
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter) {
|
||||
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, daoParamService, periodService, bsqFormatter,
|
||||
btcFormatter);
|
||||
this.blindVoteService = blindVoteService;
|
||||
}
|
||||
|
||||
|
@ -123,43 +122,43 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
|
|||
|
||||
if (voteButton != null) {
|
||||
voteButton.setOnAction(e -> {
|
||||
Coin stake = bsqFormatter.parseToCoin(stakeInputTextField.getText());
|
||||
// TODO verify stake
|
||||
Popup startPublishingPopup = new Popup<>();
|
||||
startPublishingPopup.information(Res.get("dao.proposal.blindVote.startPublishing"))
|
||||
.hideCloseButton()
|
||||
.show();
|
||||
Coin stake = bsqFormatter.parseToCoin(stakeInputTextField.getText());
|
||||
final Coin fee = BlindVoteConsensus.getFee(daoParamService, readableBsqBlockChain.getChainHeadHeight());
|
||||
Transaction dummyTx = null;
|
||||
try {
|
||||
blindVoteService.publishBlindVote(stake,
|
||||
() -> {
|
||||
startPublishingPopup.hide();
|
||||
UserThread.runAfter(() -> {
|
||||
new Popup<>().feedback(Res.get("dao.proposal.blindVote.success"))
|
||||
.show();
|
||||
}, 100, TimeUnit.MILLISECONDS);
|
||||
}, errorMessage -> {
|
||||
new Popup<>().error(errorMessage).show();
|
||||
});
|
||||
} catch (CryptoException e1) {
|
||||
//TODO show error popup
|
||||
e1.printStackTrace();
|
||||
} catch (InsufficientBsqException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (WalletException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (TransactionVerificationException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (InsufficientMoneyException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (InvalidProtocolBufferException e1) {
|
||||
e1.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
e1.printStackTrace();
|
||||
// We create a tx with dummy opreturn data to get the mining fee for confirmation popup
|
||||
dummyTx = blindVoteService.getBlindVoteTx(stake, fee, new byte[22]);
|
||||
} catch (InsufficientMoneyException | WalletException | TransactionVerificationException exception) {
|
||||
new Popup<>().warning(exception.toString()).show();
|
||||
}
|
||||
|
||||
if (dummyTx != null) {
|
||||
Coin miningFee = dummyTx.getFee();
|
||||
int txSize = dummyTx.bitcoinSerialize().length;
|
||||
GUIUtil.showBsqFeeInfoPopup(fee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.blindVote"), () -> publishBlindVote(stake));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void publishBlindVote(Coin stake) {
|
||||
voteButtonBusyAnimation.play();
|
||||
voteButtonInfoLabel.setText(Res.get("dao.blindVote.startPublishing"));
|
||||
blindVoteService.publishBlindVote(stake,
|
||||
() -> {
|
||||
voteButtonBusyAnimation.stop();
|
||||
voteButtonInfoLabel.setText("");
|
||||
new Popup().feedback(Res.get("dao.blindVote.success"))
|
||||
.show();
|
||||
}, exception -> {
|
||||
voteButtonBusyAnimation.stop();
|
||||
voteButtonInfoLabel.setText("");
|
||||
new Popup<>().warning(exception.toString()).show();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deactivate() {
|
||||
super.deactivate();
|
||||
|
@ -180,7 +179,10 @@ public class ActiveProposalsView extends BaseProposalView implements BsqBalanceL
|
|||
Res.getWithCol("dao.proposal.myVote.stake"), Layout
|
||||
.FIRST_ROW_AND_GROUP_DISTANCE - 20);
|
||||
stakeInputTextField = tuple2.second;
|
||||
voteButton = addButtonAfterGroup(root, ++gridRow, Res.get("dao.proposal.myVote.button"));
|
||||
Tuple3<Button, BusyAnimation, Label> tuple = addButtonBusyAnimationLabelAfterGroup(root, ++gridRow, Res.get("dao.proposal.myVote.button"));
|
||||
voteButton = tuple.first;
|
||||
voteButtonBusyAnimation = tuple.second;
|
||||
voteButtonInfoLabel = tuple.third;
|
||||
|
||||
voteViewItems.add(titledGroupBg);
|
||||
voteViewItems.add(tuple2.first);
|
||||
|
|
|
@ -19,10 +19,12 @@ package bisq.desktop.main.dao.proposal.closed;
|
|||
|
||||
import bisq.desktop.common.view.FxmlView;
|
||||
import bisq.desktop.main.dao.proposal.BaseProposalView;
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
|
||||
import bisq.core.dao.param.DaoParamService;
|
||||
import bisq.core.dao.vote.PeriodService;
|
||||
import bisq.core.dao.vote.proposal.ProposalService;
|
||||
|
||||
|
@ -40,8 +42,11 @@ public class ClosedProposalsView extends BaseProposalView {
|
|||
PeriodService periodService,
|
||||
BsqWalletService bsqWalletService,
|
||||
ReadableBsqBlockChain readableBsqBlockChain,
|
||||
BsqFormatter bsqFormatter) {
|
||||
super(proposalService, bsqWalletService, readableBsqBlockChain, periodService, bsqFormatter);
|
||||
DaoParamService daoParamService,
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter bsFormatter) {
|
||||
super(proposalService, bsqWalletService, readableBsqBlockChain, daoParamService, periodService,
|
||||
bsqFormatter, bsFormatter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -44,7 +44,6 @@ import bisq.core.dao.vote.proposal.generic.GenericProposalPayload;
|
|||
import bisq.core.dao.vote.proposal.generic.GenericProposalService;
|
||||
import bisq.core.locale.Res;
|
||||
import bisq.core.provider.fee.FeeService;
|
||||
import bisq.core.util.CoinUtil;
|
||||
|
||||
import bisq.network.p2p.P2PService;
|
||||
|
||||
|
@ -175,25 +174,11 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
|
|||
Coin miningFee = Objects.requireNonNull(tx).getFee();
|
||||
int txSize = tx.bitcoinSerialize().length;
|
||||
|
||||
final Coin fee = ProposalConsensus.getFee(daoParamService, readableBsqBlockChain);
|
||||
new Popup<>().headLine(Res.get("dao.proposal.create.confirm"))
|
||||
.confirmation(Res.get("dao.proposal.create.confirm.info",
|
||||
bsqFormatter.formatCoinWithCode(fee),
|
||||
btcFormatter.formatCoinWithCode(miningFee),
|
||||
CoinUtil.getFeePerByte(miningFee, txSize),
|
||||
txSize / 1000d))
|
||||
.actionButtonText(Res.get("shared.yes"))
|
||||
.onAction(() -> {
|
||||
proposalService.publishProposal(proposal,
|
||||
() -> {
|
||||
proposalDisplay.clearForm();
|
||||
proposalTypeComboBox.getSelectionModel().clearSelection();
|
||||
new Popup<>().confirmation(Res.get("dao.tx.published.success")).show();
|
||||
},
|
||||
errorMessage -> new Popup<>().warning(errorMessage).show());
|
||||
})
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
final Coin fee = ProposalConsensus.getFee(daoParamService, readableBsqBlockChain.getChainHeadHeight());
|
||||
|
||||
GUIUtil.showBsqFeeInfoPopup(fee, miningFee, txSize, bsqFormatter, btcFormatter,
|
||||
Res.get("dao.proposal"), () -> publishProposal(proposal));
|
||||
|
||||
} catch (InsufficientMoneyException e) {
|
||||
BSFormatter formatter = e instanceof InsufficientBsqException ? bsqFormatter : btcFormatter;
|
||||
new Popup<>().warning(Res.get("dao.proposal.create.missingFunds",
|
||||
|
@ -214,6 +199,16 @@ public class MakeProposalView extends ActivatableView<GridPane, Void> {
|
|||
}
|
||||
}
|
||||
|
||||
private void publishProposal(Proposal proposal) {
|
||||
proposalService.publishProposal(proposal,
|
||||
() -> {
|
||||
proposalDisplay.clearForm();
|
||||
proposalTypeComboBox.getSelectionModel().clearSelection();
|
||||
new Popup<>().confirmation(Res.get("dao.tx.published.success")).show();
|
||||
},
|
||||
errorMessage -> new Popup<>().warning(errorMessage).show());
|
||||
}
|
||||
|
||||
private Proposal createProposal(ProposalType type)
|
||||
throws InsufficientMoneyException, TransactionVerificationException, ValidationException,
|
||||
WalletException, IOException {
|
||||
|
|
|
@ -24,12 +24,14 @@ import bisq.desktop.components.HyperlinkWithIcon;
|
|||
import bisq.desktop.components.TableGroupHeadline;
|
||||
import bisq.desktop.main.dao.proposal.BaseProposalView;
|
||||
import bisq.desktop.main.dao.proposal.ProposalListItem;
|
||||
import bisq.desktop.util.BSFormatter;
|
||||
import bisq.desktop.util.BsqFormatter;
|
||||
import bisq.desktop.util.GUIUtil;
|
||||
import bisq.desktop.util.Layout;
|
||||
|
||||
import bisq.core.btc.wallet.BsqWalletService;
|
||||
import bisq.core.dao.blockchain.ReadableBsqBlockChain;
|
||||
import bisq.core.dao.param.DaoParamService;
|
||||
import bisq.core.dao.vote.PeriodService;
|
||||
import bisq.core.dao.vote.myvote.MyVoteService;
|
||||
import bisq.core.dao.vote.proposal.ProposalList;
|
||||
|
@ -92,10 +94,12 @@ public class MyVotesView extends BaseProposalView {
|
|||
MyVoteService myVoteService,
|
||||
BsqWalletService bsqWalletService,
|
||||
ReadableBsqBlockChain readableBsqBlockChain,
|
||||
DaoParamService daoParamService,
|
||||
Preferences preferences,
|
||||
BsqFormatter bsqFormatter) {
|
||||
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, periodService,
|
||||
bsqFormatter);
|
||||
BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter) {
|
||||
super(voteRequestManger, bsqWalletService, readableBsqBlockChain, daoParamService, periodService, bsqFormatter,
|
||||
btcFormatter);
|
||||
this.myVoteService = myVoteService;
|
||||
this.readableBsqBlockChain = readableBsqBlockChain;
|
||||
this.preferences = preferences;
|
||||
|
|
|
@ -33,6 +33,7 @@ import bisq.core.provider.fee.FeeService;
|
|||
import bisq.core.user.DontShowAgainLookup;
|
||||
import bisq.core.user.Preferences;
|
||||
import bisq.core.user.User;
|
||||
import bisq.core.util.CoinUtil;
|
||||
|
||||
import bisq.network.p2p.P2PService;
|
||||
|
||||
|
@ -543,4 +544,21 @@ public class GUIUtil {
|
|||
childByRowMap.get(i).forEach(child -> gridPane.getChildren().remove(child));
|
||||
}
|
||||
}
|
||||
|
||||
public static void showBsqFeeInfoPopup(Coin fee, Coin miningFee, int txSize, BsqFormatter bsqFormatter,
|
||||
BSFormatter btcFormatter, String type,
|
||||
Runnable actionHandler) {
|
||||
new Popup<>().headLine(Res.get("dao.feeTx.confirm", type))
|
||||
.confirmation(Res.get("dao.feeTx.confirm.details",
|
||||
type,
|
||||
bsqFormatter.formatCoinWithCode(fee),
|
||||
btcFormatter.formatCoinWithCode(miningFee),
|
||||
CoinUtil.getFeePerByte(miningFee, txSize),
|
||||
txSize / 1000d,
|
||||
type))
|
||||
.actionButtonText(Res.get("shared.yes"))
|
||||
.onAction(actionHandler::run)
|
||||
.closeButtonText(Res.get("shared.cancel"))
|
||||
.show();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue