Use colors for buy/sell, redesign offerbook, market overview

This commit is contained in:
Manfred Karrer 2016-02-21 22:03:37 +01:00
parent daa41d222a
commit ca20de64d9
18 changed files with 284 additions and 134 deletions

View file

@ -54,8 +54,8 @@ public final class Offer implements StoragePayload, RequiresOwnerIsOnlinePayload
@JsonExclude @JsonExclude
private static final Logger log = LoggerFactory.getLogger(Offer.class); private static final Logger log = LoggerFactory.getLogger(Offer.class);
// public static final long TTL = TimeUnit.SECONDS.toMillis(60); public static final long TTL = TimeUnit.SECONDS.toMillis(60);
public static final long TTL = TimeUnit.SECONDS.toMillis(10); //TODO // public static final long TTL = TimeUnit.SECONDS.toMillis(10); //TODO
public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " + public final static String TAC_OFFERER = "When placing that offer I accept that anyone who fulfills my conditions can " +
"take that offer."; "take that offer.";

View file

@ -30,14 +30,40 @@ bg color of non edit textFields: fafafa
-bs-very-light-grey: #f8f8f8; -bs-very-light-grey: #f8f8f8;
-fx-accent: #0f87c3; -fx-accent: #0f87c3;
-bs-blue-soft: derive(-fx-accent, 60%);
-bs-blue-transparent: #0f87c344;
-bs-green: #00aa33; -bs-green: #00aa33;
-bs-green-soft: derive(-bs-green, 60%); -bs-green-soft: derive(-bs-green, 60%);
-bs-green-transparent: #00aa3344;
-bs-error-red: #dd0000; -bs-error-red: #dd0000;
-bs-red-soft: derive(-bs-error-red, 60%); -bs-red-soft: derive(-bs-error-red, 60%);
-bs-orange: #dd8f05;
-bs-blue-transparent: #0f87c344; -bs-orange: #ff8a2b;
-bs-green-transparent: #00aa3344; -bs-yellow: #ffb60f;
-bs-turquoise: #2cacaf;
-bs-turquoise2: #1c9099;
-bs-brown: #52321b;
-bs-dark-blue: #0b456d;
-bs-dark-green: #708614;
-bs-fresh-green: #b7d042;
-bs-ocher: #de9d2c;
-bs-light-blue: #c4eef2;
-bs-smooth-red: #ed7157;
-bs-soft-red: #fe5e1c;
-bs-soft-red2: #f35e1c;
-bs-warning: -bs-orange;
-bs-buy: -bs-yellow;
-bs-buy-dark: derive(-bs-buy, -10%);
-bs-buy-transparent: derive(-bs-buy, 95%);
-bs-sell: -bs-turquoise;
-bs-sell-dark: derive(-bs-sell, -10%);
-bs-sell-transparent: derive(-bs-sell, 95%);
-fx-default-button: derive(-fx-accent, 95%); -fx-default-button: derive(-fx-accent, 95%);
-fx-focus-color: -fx-accent; -fx-focus-color: -fx-accent;
@ -625,7 +651,7 @@ textfield */
#open-support-button { #open-support-button {
-fx-font-weight: bold; -fx-font-weight: bold;
-fx-font-size: 14; -fx-font-size: 14;
-fx-base: -bs-orange; -fx-base: -bs-warning;
} }
#open-dispute-button { #open-dispute-button {
@ -783,7 +809,7 @@ textfield */
/******************************************************************************************************************** /********************************************************************************************************************
* *
* Chart * Market overview
* *
********************************************************************************************************************/ ********************************************************************************************************************/
@ -801,27 +827,27 @@ textfield */
} }
#charts .default-color0.chart-area-symbol { #charts .default-color0.chart-area-symbol {
-fx-background-color: -bs-green, white; -fx-background-color: -bs-sell, white;
} }
#charts .default-color1.chart-area-symbol { #charts .default-color1.chart-area-symbol {
-fx-background-color: -fx-accent, white; -fx-background-color: -bs-buy, white;
} }
#charts .default-color0.chart-series-area-line { #charts .default-color0.chart-series-area-line {
-fx-stroke: -bs-green; -fx-stroke: -bs-sell;
} }
#charts .default-color1.chart-series-area-line { #charts .default-color1.chart-series-area-line {
-fx-stroke: -fx-accent; -fx-stroke: -bs-buy;
} }
#charts .default-color0.chart-series-area-fill { #charts .default-color0.chart-series-area-fill {
-fx-fill: -bs-green-transparent; -fx-fill: -bs-sell-transparent;
} }
#charts .default-color1.chart-series-area-fill { #charts .default-color1.chart-series-area-fill {
-fx-fill: -bs-blue-transparent; -fx-fill: -bs-buy-transparent;
} }
#charts .axis-label { #charts .axis-label {
@ -829,6 +855,69 @@ textfield */
-fx-alignment: center; -fx-alignment: center;
} }
/********************************************************************************************************************
*
* Rounded buttons
*
********************************************************************************************************************/
#buy-button-big {
-fx-base: -bs-buy;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-font-size: 15;
-fx-background-radius: 20;
}
#buy-button-big:hover {
-fx-base: -bs-buy-dark;
}
#sell-button-big {
-fx-base: -bs-sell;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-font-size: 15;
-fx-background-radius: 20;
}
#sell-button-big:hover {
-fx-base: -bs-sell-dark;
}
#buy-button {
-fx-base: -bs-buy;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#buy-button:hover {
-fx-base: -bs-buy-dark;
}
#sell-button {
-fx-base: -bs-sell;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#sell-button:hover {
-fx-base: -bs-sell-dark;
}
#cancel-button {
-fx-base: -bs-light-grey;
-fx-text-fill: white;
-fx-font-weight: bold;
-fx-background-radius: 13;
}
#cancel-button:hover {
-fx-base: derive(-bs-light-grey, -10%);
}
/******************************************************************************************************************** /********************************************************************************************************************
* *
* Popups * Popups

View file

@ -30,10 +30,19 @@
-fx-image: url("../../../images/buy.png"); -fx-image: url("../../../images/buy.png");
} }
#image-buy-white {
-fx-image: url("../../../images/buy_white.png");
}
#image-sell { #image-sell {
-fx-image: url("../../../images/sell.png"); -fx-image: url("../../../images/sell.png");
} }
#image-sell-white {
-fx-image: url("../../../images/sell_white.png");
}
#image-expand { #image-expand {
-fx-image: url("../../../images/expand.png"); -fx-image: url("../../../images/expand.png");
} }

View file

@ -18,7 +18,7 @@
package io.bitsquare.gui.main.markets.charts; package io.bitsquare.gui.main.markets.charts;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2; import io.bitsquare.common.util.Tuple3;
import io.bitsquare.gui.Navigation; import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
@ -105,8 +105,8 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
createChart(); createChart();
Tuple2<TableView<Offer>, VBox> tupleBuy = getOfferTable(Offer.Direction.BUY); Tuple3<TableView<Offer>, VBox, Button> tupleBuy = getOfferTable(Offer.Direction.BUY);
Tuple2<TableView<Offer>, VBox> tupleSell = getOfferTable(Offer.Direction.SELL); Tuple3<TableView<Offer>, VBox, Button> tupleSell = getOfferTable(Offer.Direction.SELL);
buyOfferTableView = tupleBuy.first; buyOfferTableView = tupleBuy.first;
sellOfferTableView = tupleSell.first; sellOfferTableView = tupleSell.first;
@ -152,7 +152,7 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
} }
private Tuple2<TableView<Offer>, VBox> getOfferTable(Offer.Direction direction) { private Tuple3<TableView<Offer>, VBox, Button> getOfferTable(Offer.Direction direction) {
TableView<Offer> tableView = new TableView<>(); TableView<Offer> tableView = new TableView<>();
// price // price
@ -224,63 +224,35 @@ public class MarketsChartsView extends ActivatableViewAndModel<VBox, MarketsChar
}); });
tableView.getColumns().add(volumeColumn); tableView.getColumns().add(volumeColumn);
// select
TableColumn<Offer, Offer> selectColumn = new TableColumn<>("I want to:");
selectColumn.setMinWidth(100);
selectColumn.setCellValueFactory((offer) -> new ReadOnlyObjectWrapper<>(offer.getValue()));
selectColumn.setCellFactory(
new Callback<TableColumn<Offer, Offer>, TableCell<Offer, Offer>>() {
@Override
public TableCell<Offer, Offer> call(TableColumn<Offer, Offer> column) {
return new TableCell<Offer, Offer>() {
final Button button = new Button();
final ImageView iconView = new ImageView();
{
button.setGraphic(iconView);
button.setMinWidth(70);
}
@Override
public void updateItem(final Offer item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
boolean isSellOffer = item.getDirection() == Offer.Direction.SELL;
iconView.setId(isSellOffer ? "image-buy" : "image-sell");
button.setText(isSellOffer ? "Buy" : "Sell");
button.setOnAction(e -> {
if (isSellOffer)
navigation.navigateTo(MainView.class, BuyOfferView.class);
else
navigation.navigateTo(MainView.class, SellOfferView.class);
});
setGraphic(button);
} else {
setGraphic(null);
if (button != null)
button.setOnAction(null);
}
}
};
}
});
tableView.getColumns().add(selectColumn);
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
Label placeholder = new Label("Currently there are no offers available"); Label placeholder = new Label("Currently there are no offers available");
placeholder.setWrapText(true); placeholder.setWrapText(true);
tableView.setPlaceholder(placeholder); tableView.setPlaceholder(placeholder);
tableView.getSelectionModel().setCellSelectionEnabled(false);
Label titleLabel = new Label(direction.equals(Offer.Direction.BUY) ? "Offers for buying bitcoin (bid)" : "Offers for selling bitcoin (ask)"); Label titleLabel = new Label(direction.equals(Offer.Direction.BUY) ? "Offers for buying bitcoin (bid)" : "Offers for selling bitcoin (ask)");
titleLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-alignment: center"); titleLabel.setStyle("-fx-font-weight: bold; -fx-font-size: 16; -fx-alignment: center");
UserThread.execute(() -> titleLabel.prefWidthProperty().bind(tableView.widthProperty())); UserThread.execute(() -> titleLabel.prefWidthProperty().bind(tableView.widthProperty()));
boolean isSellOffer = direction == Offer.Direction.SELL;
Button button = new Button();
ImageView iconView = new ImageView();
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");
button.setGraphic(iconView);
button.setGraphicTextGap(10);
button.setText(isSellOffer ? "I want to buy bitcoin" : "I want to sell bitcoin");
button.setMinHeight(40);
button.setId(isSellOffer ? "buy-button-big" : "sell-button-big");
button.setOnAction(e -> navigation.navigateTo(MainView.class, isSellOffer ? BuyOfferView.class : SellOfferView.class));
VBox vBox = new VBox(); VBox vBox = new VBox();
vBox.setSpacing(10); vBox.setSpacing(10);
vBox.setFillWidth(true); vBox.setFillWidth(true);
vBox.setMinHeight(150); vBox.setMinHeight(120);
vBox.getChildren().addAll(titleLabel, tableView); vBox.getChildren().addAll(titleLabel, tableView, button);
return new Tuple2<>(tableView, vBox);
button.prefWidthProperty().bind(vBox.widthProperty());
return new Tuple3<>(tableView, vBox, button);
} }

View file

@ -82,10 +82,10 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
private BalanceTextField balanceTextField; private BalanceTextField balanceTextField;
private ProgressIndicator placeOfferSpinner; private ProgressIndicator placeOfferSpinner;
private TitledGroupBg payFundsPane; private TitledGroupBg payFundsPane;
private Button nextButton, cancelButton1, cancelButton2, placeOfferButton; private Button nextButton, cancelButton1, cancelButton2, createOfferButton;
private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField; private InputTextField amountTextField, minAmountTextField, priceTextField, volumeTextField;
private TextField totalToPayTextField, currencyTextField; private TextField totalToPayTextField, currencyTextField;
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel, private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, amountBtcLabel, priceCurrencyLabel,
volumeCurrencyLabel, minAmountBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, placeOfferSpinnerInfoLabel, currencyTextFieldLabel, volumeCurrencyLabel, minAmountBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, placeOfferSpinnerInfoLabel, currencyTextFieldLabel,
currencyComboBoxLabel; currencyComboBoxLabel;
private ComboBox<PaymentAccount> paymentAccountsComboBox; private ComboBox<PaymentAccount> paymentAccountsComboBox;
@ -156,7 +156,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
addBindings(); addBindings();
addListeners(); addListeners();
buyLabel.setText(model.getDirectionLabel()); directionLabel.setText(model.getDirectionLabel());
amountDescriptionLabel.setText(model.getAmountDescription()); amountDescriptionLabel.setText(model.getAmountDescription());
addressTextField.setAddress(model.getAddressAsString()); addressTextField.setAddress(model.getAddressAsString());
addressTextField.setPaymentLabel(model.getPaymentLabel()); addressTextField.setPaymentLabel(model.getPaymentLabel());
@ -181,12 +181,24 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) { public void initWithData(Offer.Direction direction, TradeCurrency tradeCurrency) {
model.initWithData(direction, tradeCurrency); model.initWithData(direction, tradeCurrency);
ImageView iconView = new ImageView();
createOfferButton.setGraphic(iconView);
if (direction == Offer.Direction.BUY) { if (direction == Offer.Direction.BUY) {
imageView.setId("image-buy-large"); imageView.setId("image-buy-large");
createOfferButton.setId("buy-button-big");
nextButton.setId("buy-button");
createOfferButton.setText("Place offer for buying bitcoin");
iconView.setId("image-buy-white");
} else { } else {
imageView.setId("image-sell-large"); imageView.setId("image-sell-large");
// only needed for sell // only needed for sell
totalToPayTextField.setPromptText(BSResources.get("createOffer.fundsBox.totalsNeeded.prompt")); totalToPayTextField.setPromptText(BSResources.get("createOffer.fundsBox.totalsNeeded.prompt"));
createOfferButton.setId("sell-button-big");
nextButton.setId("sell-button");
createOfferButton.setText("Place offer for selling bitcoin");
iconView.setId("image-sell-white");
} }
} }
@ -354,8 +366,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
volumeTextField.validationResultProperty().bind(model.volumeValidationResult); volumeTextField.validationResultProperty().bind(model.volumeValidationResult);
// buttons // buttons
placeOfferButton.visibleProperty().bind(model.isPlaceOfferButtonVisible); createOfferButton.visibleProperty().bind(model.isPlaceOfferButtonVisible);
placeOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled); createOfferButton.disableProperty().bind(model.isPlaceOfferButtonDisabled);
placeOfferSpinnerInfoLabel.visibleProperty().bind(model.isPlaceOfferSpinnerVisible); placeOfferSpinnerInfoLabel.visibleProperty().bind(model.isPlaceOfferSpinnerVisible);
@ -387,8 +399,8 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
minAmountTextField.validationResultProperty().unbind(); minAmountTextField.validationResultProperty().unbind();
priceTextField.validationResultProperty().unbind(); priceTextField.validationResultProperty().unbind();
volumeTextField.validationResultProperty().unbind(); volumeTextField.validationResultProperty().unbind();
placeOfferButton.visibleProperty().unbind(); createOfferButton.visibleProperty().unbind();
placeOfferButton.disableProperty().unbind(); createOfferButton.disableProperty().unbind();
placeOfferSpinnerInfoLabel.visibleProperty().unbind(); placeOfferSpinnerInfoLabel.visibleProperty().unbind();
currencyComboBox.managedProperty().unbind(); currencyComboBox.managedProperty().unbind();
currencyComboBoxLabel.visibleProperty().unbind(); currencyComboBoxLabel.visibleProperty().unbind();
@ -613,14 +625,14 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
imageView = new ImageView(); imageView = new ImageView();
imageView.setPickOnBounds(true); imageView.setPickOnBounds(true);
buyLabel = new Label(); directionLabel = new Label();
buyLabel.setId("direction-icon-label"); directionLabel.setAlignment(Pos.CENTER);
buyLabel.setAlignment(Pos.CENTER); directionLabel.setPadding(new Insets(-5, 0, 0, 0));
buyLabel.setPadding(new Insets(-5, 0, 0, 0)); directionLabel.setId("direction-icon-label");
VBox imageVBox = new VBox(); VBox imageVBox = new VBox();
imageVBox.setAlignment(Pos.CENTER); imageVBox.setAlignment(Pos.CENTER);
imageVBox.setSpacing(6); imageVBox.setSpacing(6);
imageVBox.getChildren().addAll(imageView, buyLabel); imageVBox.getChildren().addAll(imageView, directionLabel);
GridPane.setRowIndex(imageVBox, gridRow); GridPane.setRowIndex(imageVBox, gridRow);
GridPane.setRowSpan(imageVBox, 2); GridPane.setRowSpan(imageVBox, 2);
GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10)); GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10));
@ -636,9 +648,9 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
cancelButton1 = tuple.second; cancelButton1 = tuple.second;
cancelButton1.setDefaultButton(false); cancelButton1.setDefaultButton(false);
cancelButton1.setOnAction(e -> close()); cancelButton1.setOnAction(e -> close());
cancelButton1.setId("cancel-button");
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0)); GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
nextButton.setId("show-details-button");
nextButton.setOnAction(e -> onShowFundsScreen()); nextButton.setOnAction(e -> onShowFundsScreen());
} }
@ -679,11 +691,11 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
balanceTextField = balanceTuple.second; balanceTextField = balanceTuple.second;
balanceTextField.setVisible(false); balanceTextField.setVisible(false);
Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, Tuple3<Button, ProgressIndicator, Label> placeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "");
BSResources.get("createOffer.fundsBox.placeOffer")); createOfferButton = placeOfferTuple.first;
placeOfferButton = placeOfferTuple.first; createOfferButton.setVisible(false);
placeOfferButton.setVisible(false); createOfferButton.setOnAction(e -> onPlaceOffer());
placeOfferButton.setOnAction(e -> onPlaceOffer()); createOfferButton.setMinHeight(40);
placeOfferSpinner = placeOfferTuple.second; placeOfferSpinner = placeOfferTuple.second;
placeOfferSpinner.setPrefSize(18, 18); placeOfferSpinner.setPrefSize(18, 18);
placeOfferSpinnerInfoLabel = placeOfferTuple.third; placeOfferSpinnerInfoLabel = placeOfferTuple.third;
@ -694,6 +706,7 @@ public class CreateOfferView extends ActivatableViewAndModel<AnchorPane, CreateO
cancelButton2.setOnAction(e -> close()); cancelButton2.setOnAction(e -> close());
cancelButton2.setDefaultButton(false); cancelButton2.setDefaultButton(false);
cancelButton2.setVisible(false); cancelButton2.setVisible(false);
cancelButton2.setId("cancel-button");
} }
private void addAmountPriceFields() { private void addAmountPriceFields() {

View file

@ -17,18 +17,12 @@
~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. ~ along with Bitsquare. If not, see <http://www.gnu.org/licenses/>.
--> -->
<?import javafx.scene.layout.*?> <?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.offer.offerbook.OfferBookView" <GridPane fx:id="root" fx:controller="io.bitsquare.gui.main.offer.offerbook.OfferBookView"
hgap="5.0" vgap="5" hgap="5.0" vgap="5"
xmlns:fx="http://javafx.com/fxml"> xmlns:fx="http://javafx.com/fxml">
<rowConstraints>
<RowConstraints/>
<RowConstraints/>
<RowConstraints/>
<RowConstraints vgrow="ALWAYS"/>
</rowConstraints>
<columnConstraints> <columnConstraints>
<ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/> <ColumnConstraints halignment="RIGHT" hgrow="SOMETIMES" minWidth="200"/>
<ColumnConstraints hgrow="ALWAYS"/> <ColumnConstraints hgrow="ALWAYS"/>

View file

@ -21,7 +21,7 @@ import io.bitsquare.gui.Navigation;
import io.bitsquare.gui.common.view.ActivatableViewAndModel; import io.bitsquare.gui.common.view.ActivatableViewAndModel;
import io.bitsquare.gui.common.view.FxmlView; import io.bitsquare.gui.common.view.FxmlView;
import io.bitsquare.gui.components.HyperlinkWithIcon; import io.bitsquare.gui.components.HyperlinkWithIcon;
import io.bitsquare.gui.components.TableGroupHeadline; import io.bitsquare.gui.components.TitledGroupBg;
import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.MainView;
import io.bitsquare.gui.main.account.AccountView; import io.bitsquare.gui.main.account.AccountView;
import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView; import io.bitsquare.gui.main.account.content.arbitratorselection.ArbitratorSelectionView;
@ -38,10 +38,13 @@ import io.bitsquare.locale.TradeCurrency;
import io.bitsquare.payment.PaymentMethod; import io.bitsquare.payment.PaymentMethod;
import io.bitsquare.trade.offer.Offer; import io.bitsquare.trade.offer.Offer;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.geometry.HPos;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import javafx.geometry.VPos;
import javafx.scene.control.*; import javafx.scene.control.*;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.layout.Priority;
import javafx.util.Callback; import javafx.util.Callback;
import javafx.util.StringConverter; import javafx.util.StringConverter;
@ -64,7 +67,7 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
private OfferView.OfferActionHandler offerActionHandler; private OfferView.OfferActionHandler offerActionHandler;
private int gridRow = 0; private int gridRow = 0;
private TableGroupHeadline offerBookTitle; private TitledGroupBg offerBookTitle;
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
@ -81,8 +84,9 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
@Override @Override
public void initialize() { public void initialize() {
root.setPadding(new Insets(30, 25, -1, 25)); root.setPadding(new Insets(20, 25, 5, 25));
addTitledGroupBg(root, gridRow, 2, "Filter offer book");
offerBookTitle = addTitledGroupBg(root, gridRow, 3, "");
currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second; currencyComboBox = addLabelComboBox(root, gridRow, "Filter by currency:", Layout.FIRST_ROW_DISTANCE).second;
currencyComboBox.setPromptText("Select currency"); currencyComboBox.setPromptText("Select currency");
@ -116,21 +120,15 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
} }
}); });
// createOfferButton
createOfferButton = addButtonAfterGroup(root, ++gridRow, "Create new offer");
offerBookTitle = new TableGroupHeadline("");
GridPane.setRowIndex(offerBookTitle, ++gridRow);
GridPane.setColumnSpan(offerBookTitle, 2);
GridPane.setMargin(offerBookTitle, new Insets(20, -10, -10, -10));
root.getChildren().add(offerBookTitle);
tableView = new TableView<>(); tableView = new TableView<>();
GridPane.setRowIndex(tableView, gridRow);
GridPane.setRowIndex(tableView, ++gridRow);
GridPane.setColumnIndex(tableView, 0);
GridPane.setColumnSpan(tableView, 2); GridPane.setColumnSpan(tableView, 2);
GridPane.setMargin(tableView, new Insets(40, -10, -15, -10)); GridPane.setMargin(tableView, new Insets(10, -10, -10, -10));
GridPane.setVgrow(tableView, Priority.ALWAYS);
root.getChildren().add(tableView); root.getChildren().add(tableView);
amountColumn = getAmountColumn(); amountColumn = getAmountColumn();
tableView.getColumns().add(amountColumn); tableView.getColumns().add(amountColumn);
priceColumn = getPriceColumn(); priceColumn = getPriceColumn();
@ -151,6 +149,15 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
amountColumn.setComparator((o1, o2) -> o1.getOffer().getAmount().compareTo(o2.getOffer().getAmount())); amountColumn.setComparator((o1, o2) -> o1.getOffer().getAmount().compareTo(o2.getOffer().getAmount()));
volumeColumn.setComparator((o1, o2) -> o1.getOffer().getOfferVolume().compareTo(o2.getOffer().getOfferVolume())); volumeColumn.setComparator((o1, o2) -> o1.getOffer().getOfferVolume().compareTo(o2.getOffer().getOfferVolume()));
paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod())); paymentMethodColumn.setComparator((o1, o2) -> o1.getOffer().getPaymentMethod().compareTo(o2.getOffer().getPaymentMethod()));
createOfferButton = addButton(root, ++gridRow, "");
createOfferButton.setMinHeight(40);
createOfferButton.setPadding(new Insets(0, 20, 0, 20));
createOfferButton.setGraphicTextGap(10);
GridPane.setMargin(createOfferButton, new Insets(15, 0, 0, 0));
GridPane.setHalignment(createOfferButton, HPos.RIGHT);
GridPane.setVgrow(createOfferButton, Priority.NEVER);
GridPane.setValignment(createOfferButton, VPos.TOP);
} }
@Override @Override
@ -211,8 +218,21 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
} }
public void setDirection(Offer.Direction direction) { public void setDirection(Offer.Direction direction) {
offerBookTitle.setText(direction == Offer.Direction.SELL ? "Offers for buying bitcoin " : "Offers for selling bitcoin ");
model.setDirection(direction); model.setDirection(direction);
ImageView iconView = new ImageView();
createOfferButton.setGraphic(iconView);
if (direction == Offer.Direction.SELL) {
offerBookTitle.setText("Offers for buying bitcoin ");
createOfferButton.setId("sell-button-big");
createOfferButton.setText("Create new offer for selling bitcoin");
iconView.setId("image-sell-white");
} else {
offerBookTitle.setText("Offers for selling bitcoin ");
createOfferButton.setId("buy-button-big");
createOfferButton.setText("Create new offer for buying bitcoin");
iconView.setId("image-buy-white");
}
} }
public void setOfferActionHandler(OfferView.OfferActionHandler offerActionHandler) { public void setOfferActionHandler(OfferView.OfferActionHandler offerActionHandler) {
@ -456,7 +476,10 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
{ {
button.setGraphic(iconView); button.setGraphic(iconView);
button.setMinWidth(70); button.setMinWidth(150);
button.setMaxWidth(150);
button.setGraphicTextGap(10);
button.setStyle("-fx-text-fill: white;");
} }
@Override @Override
@ -495,9 +518,12 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
if (myOffer) { if (myOffer) {
iconView.setId("image-remove"); iconView.setId("image-remove");
title = "Remove"; title = "Remove";
button.setId("cancel-button");
button.setOnAction(e -> onRemoveOpenOffer(offer)); button.setOnAction(e -> onRemoveOpenOffer(offer));
} else { } else {
iconView.setId(offer.getDirection() == Offer.Direction.SELL ? "image-buy" : "image-sell"); boolean isSellOffer = offer.getDirection() == Offer.Direction.SELL;
iconView.setId(isSellOffer ? "image-buy-white" : "image-sell-white");
button.setId(isSellOffer ? "buy-button" : "sell-button");
title = model.getDirectionLabel(offer); title = model.getDirectionLabel(offer);
button.setOnAction(e -> onTakeOffer(offer)); button.setOnAction(e -> onTakeOffer(offer));
} }
@ -505,7 +531,6 @@ public class OfferBookView extends ActivatableViewAndModel<GridPane, OfferBookVi
if (!isTradable) if (!isTradable)
button.setOnAction(e -> onShowInfo(isPaymentAccountValidForOffer, hasMatchingArbitrator, hasSameProtocolVersion)); button.setOnAction(e -> onShowInfo(isPaymentAccountValidForOffer, hasMatchingArbitrator, hasSameProtocolVersion));
button.setText(title); button.setText(title);
setGraphic(button); setGraphic(button);
} else { } else {

View file

@ -83,7 +83,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
private Button nextButton, takeOfferButton, cancelButton1, cancelButton2; private Button nextButton, takeOfferButton, cancelButton1, cancelButton2;
private InputTextField amountTextField; private InputTextField amountTextField;
private TextField paymentMethodTextField, currencyTextField, priceTextField, volumeTextField, amountRangeTextField; private TextField paymentMethodTextField, currencyTextField, priceTextField, volumeTextField, amountRangeTextField;
private Label buyLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel, private Label directionLabel, amountDescriptionLabel, addressLabel, balanceLabel, totalToPayLabel, totalToPayInfoIconLabel,
amountBtcLabel, priceCurrencyLabel, amountBtcLabel, priceCurrencyLabel,
volumeCurrencyLabel, amountRangeBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, takeOfferSpinnerInfoLabel; volumeCurrencyLabel, amountRangeBtcLabel, priceDescriptionLabel, volumeDescriptionLabel, takeOfferSpinnerInfoLabel;
private TextFieldWithCopyIcon totalToPayTextField; private TextFieldWithCopyIcon totalToPayTextField;
@ -303,10 +303,25 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
public void initWithData(Offer offer) { public void initWithData(Offer offer) {
model.initWithData(offer); model.initWithData(offer);
if (model.getOffer().getDirection() == Offer.Direction.SELL) ImageView iconView = new ImageView();
takeOfferButton.setGraphic(iconView);
if (model.getOffer().getDirection() == Offer.Direction.SELL) {
imageView.setId("image-buy-large"); imageView.setId("image-buy-large");
else directionLabel.setId("direction-icon-label-buy");
takeOfferButton.setId("buy-button-big");
takeOfferButton.setText("Take offer for buying bitcoin");
nextButton.setId("buy-button");
iconView.setId("image-buy-white");
} else {
imageView.setId("image-sell-large"); imageView.setId("image-sell-large");
directionLabel.setId("direction-icon-label-sell");
takeOfferButton.setId("sell-button-big");
nextButton.setId("sell-button");
takeOfferButton.setText("Take offer for selling bitcoin");
iconView.setId("image-sell-white");
}
balanceTextField.setup(model.address.get(), model.getFormatter()); balanceTextField.setup(model.address.get(), model.getFormatter());
@ -322,7 +337,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
if (!showComboBox) if (!showComboBox)
paymentMethodTextField.setText(BSResources.get(model.getPaymentMethod().getId())); paymentMethodTextField.setText(BSResources.get(model.getPaymentMethod().getId()));
currencyTextField.setText(model.dataModel.getCurrencyNameAndCode()); currencyTextField.setText(model.dataModel.getCurrencyNameAndCode());
buyLabel.setText(model.getDirectionLabel()); directionLabel.setText(model.getDirectionLabel());
amountDescriptionLabel.setText(model.getAmountDescription()); amountDescriptionLabel.setText(model.getAmountDescription());
amountRangeTextField.setText(model.getAmountRange()); amountRangeTextField.setText(model.getAmountRange());
priceTextField.setText(model.getPrice()); priceTextField.setText(model.getPrice());
@ -493,14 +508,13 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
imageView = new ImageView(); imageView = new ImageView();
imageView.setPickOnBounds(true); imageView.setPickOnBounds(true);
buyLabel = new Label(); directionLabel = new Label();
buyLabel.setId("direction-icon-label"); directionLabel.setAlignment(Pos.CENTER);
buyLabel.setAlignment(Pos.CENTER); directionLabel.setPadding(new Insets(-5, 0, 0, 0));
buyLabel.setPadding(new Insets(-5, 0, 0, 0));
VBox imageVBox = new VBox(); VBox imageVBox = new VBox();
imageVBox.setAlignment(Pos.CENTER); imageVBox.setAlignment(Pos.CENTER);
imageVBox.setSpacing(6); imageVBox.setSpacing(6);
imageVBox.getChildren().addAll(imageView, buyLabel); imageVBox.getChildren().addAll(imageView, directionLabel);
GridPane.setRowIndex(imageVBox, gridRow); GridPane.setRowIndex(imageVBox, gridRow);
GridPane.setRowSpan(imageVBox, 2); GridPane.setRowSpan(imageVBox, 2);
GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10)); GridPane.setMargin(imageVBox, new Insets(Layout.FIRST_ROW_AND_GROUP_DISTANCE, 10, 10, 10));
@ -516,9 +530,9 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
cancelButton1 = tuple.second; cancelButton1 = tuple.second;
cancelButton1.setDefaultButton(false); cancelButton1.setDefaultButton(false);
cancelButton1.setOnAction(e -> close()); cancelButton1.setOnAction(e -> close());
cancelButton1.setId("cancel-button");
GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0)); GridPane.setMargin(nextButton, new Insets(-35, 0, 0, 0));
nextButton.setId("show-details-button");
nextButton.setOnAction(e -> onShowPayFundsScreen()); nextButton.setOnAction(e -> onShowPayFundsScreen());
} }
@ -560,10 +574,11 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
balanceTextField = balanceTuple.second; balanceTextField = balanceTuple.second;
balanceTextField.setVisible(false); balanceTextField.setVisible(false);
Tuple3<Button, ProgressIndicator, Label> takeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, BSResources.get("takeOffer.fundsBox.takeOffer")); Tuple3<Button, ProgressIndicator, Label> takeOfferTuple = addButtonWithStatusAfterGroup(gridPane, ++gridRow, "");
takeOfferButton = takeOfferTuple.first; takeOfferButton = takeOfferTuple.first;
takeOfferButton.setVisible(false); takeOfferButton.setVisible(false);
takeOfferButton.setOnAction(e -> onTakeOffer()); takeOfferButton.setOnAction(e -> onTakeOffer());
takeOfferButton.setMinHeight(40);
takeOfferSpinner = takeOfferTuple.second; takeOfferSpinner = takeOfferTuple.second;
takeOfferSpinner.setPrefSize(18, 18); takeOfferSpinner.setPrefSize(18, 18);
takeOfferSpinnerInfoLabel = takeOfferTuple.third; takeOfferSpinnerInfoLabel = takeOfferTuple.third;
@ -574,6 +589,7 @@ public class TakeOfferView extends ActivatableViewAndModel<AnchorPane, TakeOffer
cancelButton2.setOnAction(e -> close()); cancelButton2.setOnAction(e -> close());
cancelButton2.setDefaultButton(false); cancelButton2.setDefaultButton(false);
cancelButton2.setVisible(false); cancelButton2.setVisible(false);
cancelButton2.setId("cancel-button");
} }
private void addAmountPriceFields() { private void addAmountPriceFields() {

View file

@ -248,7 +248,7 @@ public class PendingTradesView extends ActivatableViewAndModel<VBox, PendingTrad
if (model.showDispute(item.getTrade())) { if (model.showDispute(item.getTrade())) {
setStyle("-fx-text-fill: -bs-error-red"); setStyle("-fx-text-fill: -bs-error-red");
} else if (model.showWarning(item.getTrade())) { } else if (model.showWarning(item.getTrade())) {
setStyle("-fx-text-fill: -bs-orange"); setStyle("-fx-text-fill: -bs-warning");
} else { } else {
setId("-fx-text-fill: black"); setId("-fx-text-fill: black");
} }

View file

@ -609,6 +609,23 @@ public class FormBuilder {
} }
///////////////////////////////////////////////////////////////////////////////////////////
// Label + Button
///////////////////////////////////////////////////////////////////////////////////////////
public static Tuple2<Label, Button> addLabelButton(GridPane gridPane, int rowIndex, String labelText, String buttonTitle, double top) {
Label label = addLabel(gridPane, rowIndex, labelText, top);
Button button = new Button(buttonTitle);
button.setDefaultButton(true);
GridPane.setRowIndex(button, rowIndex);
GridPane.setColumnIndex(button, 1);
gridPane.getChildren().add(button);
GridPane.setMargin(button, new Insets(top, 0, 0, 0));
return new Tuple2<>(label, button);
}
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////
// Button // Button
/////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 650 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 691 B

View file

@ -6,6 +6,7 @@ import io.bitsquare.app.Log;
import io.bitsquare.app.Version; import io.bitsquare.app.Version;
import io.bitsquare.common.ByteArrayUtils; import io.bitsquare.common.ByteArrayUtils;
import io.bitsquare.common.UserThread; import io.bitsquare.common.UserThread;
import io.bitsquare.common.util.Tuple2;
import io.bitsquare.crypto.PrefixedSealedAndSignedMessage; import io.bitsquare.crypto.PrefixedSealedAndSignedMessage;
import io.bitsquare.p2p.Message; import io.bitsquare.p2p.Message;
import io.bitsquare.p2p.NodeAddress; import io.bitsquare.p2p.NodeAddress;
@ -58,10 +59,10 @@ public class Connection implements MessageListener {
private static final int MAX_MSG_SIZE = 100 * 1024; // 100 kb of compressed data private static final int MAX_MSG_SIZE = 100 * 1024; // 100 kb of compressed data
private static final int MSG_THROTTLE_PER_SEC = 10; // With MAX_MSG_SIZE of 100kb results in bandwidth of 10 mbit/sec private static final int MSG_THROTTLE_PER_SEC = 10; // With MAX_MSG_SIZE of 100kb results in bandwidth of 10 mbit/sec
private static final int MSG_THROTTLE_PER_10SEC = 50; // With MAX_MSG_SIZE of 100kb results in bandwidth of 5 mbit/sec for 10 sec private static final int MSG_THROTTLE_PER_10_SEC = 50; // With MAX_MSG_SIZE of 100kb results in bandwidth of 5 mbit/sec for 10 sec
// private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60); private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(60);
//TODO //TODO
private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30); // private static final int SOCKET_TIMEOUT = (int) TimeUnit.SECONDS.toMillis(30);
public static int getMaxMsgSize() { public static int getMaxMsgSize() {
return MAX_MSG_SIZE; return MAX_MSG_SIZE;
@ -96,7 +97,7 @@ public class Connection implements MessageListener {
private final boolean useCompression = false; private final boolean useCompression = false;
private PeerType peerType; private PeerType peerType;
private final ObjectProperty<NodeAddress> nodeAddressProperty = new SimpleObjectProperty<>(); private final ObjectProperty<NodeAddress> nodeAddressProperty = new SimpleObjectProperty<>();
private final List<Long> messageTimeStamps = new ArrayList<>(); private final List<Tuple2<Long, Serializable>> messageTimeStamps = new ArrayList<>();
private final CopyOnWriteArraySet<MessageListener> messageListeners = new CopyOnWriteArraySet<>(); private final CopyOnWriteArraySet<MessageListener> messageListeners = new CopyOnWriteArraySet<>();
@ -231,28 +232,40 @@ public class Connection implements MessageListener {
sharedModel.reportInvalidRequest(ruleViolation); sharedModel.reportInvalidRequest(ruleViolation);
} }
private boolean violatesThrottleLimit() { private boolean violatesThrottleLimit(Serializable serializable) {
long now = System.currentTimeMillis(); long now = System.currentTimeMillis();
boolean violated = false; boolean violated = false;
//TODO remove serializable storage after network is tested stable
if (messageTimeStamps.size() >= MSG_THROTTLE_PER_SEC) { if (messageTimeStamps.size() >= MSG_THROTTLE_PER_SEC) {
// check if we got more than 10 (MSG_THROTTLE_PER_SEC) msg per sec. // check if we got more than 10 (MSG_THROTTLE_PER_SEC) msg per sec.
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_SEC); long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_SEC).first;
// if duration < 1 sec we received too much messages // if duration < 1 sec we received too much messages
violated = now - compareValue < TimeUnit.SECONDS.toMillis(1); violated = now - compareValue < TimeUnit.SECONDS.toMillis(1);
if (violated) {
log.error("violatesThrottleLimit 1 ");
log.error("compareValue " + compareValue);
log.error("messageTimeStamps: \n\t" + messageTimeStamps.stream().map(e -> e.second.toString() + "\n\t").toString());
}
} }
if (messageTimeStamps.size() >= MSG_THROTTLE_PER_10SEC) { if (messageTimeStamps.size() >= MSG_THROTTLE_PER_10_SEC) {
if (!violated) { if (!violated) {
// check if we got more than 50 msg per 10 sec. // check if we got more than 50 msg per 10 sec.
long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_10SEC); long compareValue = messageTimeStamps.get(messageTimeStamps.size() - MSG_THROTTLE_PER_10_SEC).first;
// if duration < 10 sec we received too much messages // if duration < 10 sec we received too much messages
violated = now - compareValue < TimeUnit.SECONDS.toMillis(10); violated = now - compareValue < TimeUnit.SECONDS.toMillis(10);
if (violated) {
log.error("violatesThrottleLimit 2 ");
log.error("compareValue " + compareValue);
log.error("messageTimeStamps: \n\t" + messageTimeStamps.stream().map(e -> e.second.toString() + "\n\t").toString());
}
} }
// we limit to max 50 (MSG_THROTTLE_PER_10SEC) entries // we limit to max 50 (MSG_THROTTLE_PER_10SEC) entries
messageTimeStamps.remove(0); messageTimeStamps.remove(0);
} }
messageTimeStamps.add(now); messageTimeStamps.add(new Tuple2<>(now, serializable));
return violated; return violated;
} }
@ -641,7 +654,7 @@ public class Connection implements MessageListener {
return; return;
} }
if (sharedModel.connection.violatesThrottleLimit()) { if (sharedModel.connection.violatesThrottleLimit(serializable)) {
reportInvalidRequest(RuleViolation.THROTTLE_LIMIT_EXCEEDED); reportInvalidRequest(RuleViolation.THROTTLE_LIMIT_EXCEEDED);
return; return;
} }

View file

@ -17,13 +17,14 @@ import org.slf4j.LoggerFactory;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Random;
public class KeepAliveManager implements MessageListener, ConnectionListener, PeerManager.Listener { public class KeepAliveManager implements MessageListener, ConnectionListener, PeerManager.Listener {
private static final Logger log = LoggerFactory.getLogger(KeepAliveManager.class); private static final Logger log = LoggerFactory.getLogger(KeepAliveManager.class);
//private static final int INTERVAL_SEC = new Random().nextInt(10) + 10; private static final int INTERVAL_SEC = new Random().nextInt(10) + 10;
//TODO //TODO
private static final int INTERVAL_SEC = 5; // private static final int INTERVAL_SEC = 5;
private final NetworkNode networkNode; private final NetworkNode networkNode;
private final PeerManager peerManager; private final PeerManager peerManager;

View file

@ -39,7 +39,8 @@ public class P2PDataStorage implements MessageListener, ConnectionListener {
@VisibleForTesting @VisibleForTesting
//public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(30); //public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(30);
public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(5);//TODO public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.HOURS.toMillis(30);
// public static int CHECK_TTL_INTERVAL_MILLIS = (int) TimeUnit.SECONDS.toMillis(5);//TODO
private final Broadcaster broadcaster; private final Broadcaster broadcaster;
private final Map<ByteArray, ProtectedData> map = new ConcurrentHashMap<>(); private final Map<ByteArray, ProtectedData> map = new ConcurrentHashMap<>();

View file

@ -60,7 +60,7 @@ public class ProtectedData implements Payload {
", ttl=" + ttl + ", ttl=" + ttl +
", date=" + date + ", date=" + date +
", sequenceNumber=" + sequenceNumber + ", sequenceNumber=" + sequenceNumber +
", ownerStoragePubKey.hashCode()=" + ownerPubKey.hashCode() + ", ownerPubKey.hashCode()=" + ownerPubKey.hashCode() +
", signature.hashCode()=" + Arrays.toString(signature).hashCode() + ", signature.hashCode()=" + Arrays.toString(signature).hashCode() +
'}'; '}';
} }