Skip to content

Commit

Permalink
Merge pull request #5423 from jmacxx/dupOffer_2
Browse files Browse the repository at this point in the history
Functionality to duplicate an offer
  • Loading branch information
ripcurlx authored Apr 22, 2021
2 parents 0852bce + a5d5eaf commit c17b46f
Show file tree
Hide file tree
Showing 27 changed files with 472 additions and 70 deletions.
9 changes: 6 additions & 3 deletions core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,9 @@ portfolio.tab.pendingTrades=Open trades
portfolio.tab.history=History
portfolio.tab.failed=Failed
portfolio.tab.editOpenOffer=Edit offer
portfolio.tab.duplicateOffer=Duplicate offer
portfolio.context.offerLikeThis=Create new offer like this...
portfolio.context.notYourOffer=You can only duplicate offers where you were the maker.

portfolio.closedTrades.deviation.help=Percentage price deviation from market

Expand Down Expand Up @@ -2945,9 +2948,9 @@ popup.shutDownInProgress.headline=Shut down in progress
popup.shutDownInProgress.msg=Shutting down application can take a few seconds.\nPlease don't interrupt this process.

popup.attention.forTradeWithId=Attention required for trade with ID {0}
popup.attention.reasonForPaymentRuleChange=Version 1.5.5 introduces a critical trade rule change regarding \
the \"reason for payment\" field in bank transfers. Please leave this field empty -- \
DO NOT use the trade ID as \"reason for payment\" anymore.
popup.attention.newFeatureDuplicateOffer=Version 1.6.3 introduces a new feature allowing easy re-entry of offers \
by right-clicking on an existing offer or trade and choosing `Create new offer like this`. This is useful for \
traders who frequently make the same offer.

popup.info.multiplePaymentAccounts.headline=Multiple payment accounts available
popup.info.multiplePaymentAccounts.msg=You have multiple payment accounts available for this offer. Please make sure you've picked the right one.
Expand Down
6 changes: 1 addition & 5 deletions desktop/src/main/java/bisq/desktop/Navigation.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ public final class Navigation implements PersistedDataHost {
private static final ViewPath DEFAULT_VIEW_PATH = ViewPath.to(MainView.class, MarketView.class);

public interface Listener {
void onNavigationRequested(ViewPath path);

default void onNavigationRequested(ViewPath path, @Nullable Object data) {
}
void onNavigationRequested(ViewPath path, @Nullable Object data);
}

// New listeners can be added during iteration so we use CopyOnWriteArrayList to
Expand Down Expand Up @@ -137,7 +134,6 @@ public void navigateTo(ViewPath newPath, @Nullable Object data) {

currentPath = newPath;
previousPath = currentPath;
listeners.forEach((e) -> e.onNavigationRequested(currentPath));
listeners.forEach((e) -> e.onNavigationRequested(currentPath, data));
requestPersistence();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ public View load(Class<? extends View> viewClass) {
cache.put(viewClass, view);
return view;
}

public void removeFromCache(Class<? extends View> viewClass) {
cache.remove(viewClass);
}
}
2 changes: 1 addition & 1 deletion desktop/src/main/java/bisq/desktop/main/MainView.java
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ protected Tooltip computeValue() {
setupBadge(supportButtonWithBadge, model.getNumOpenSupportTickets(), model.getShowOpenSupportTicketsNotification());
setupBadge(settingsButtonWithBadge, new SimpleStringProperty(Res.get("shared.new")), model.getShowSettingsUpdatesNotification());

navigation.addListener(viewPath -> {
navigation.addListener((viewPath, data) -> {
if (viewPath.size() != 2 || viewPath.indexOf(MainView.class) != 0)
return;

Expand Down
14 changes: 3 additions & 11 deletions desktop/src/main/java/bisq/desktop/main/MainViewModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -278,22 +278,14 @@ public void onSetupComplete() {

// We only show the popup if the user has already set up any fiat account. For new users it is not a rule
// change and for altcoins its not relevant.
String key = "reasonForPaymentChange";
boolean hasFiatAccount = user.getPaymentAccounts() != null &&
user.getPaymentAccounts().stream()
.filter(e -> !(e.getPaymentAccountPayload() instanceof AssetsAccountPayload))
.findAny()
.isPresent();
if (hasFiatAccount && DontShowAgainLookup.showAgain(key)) {
String key = "newFeatureDuplicateOffer";
if (DontShowAgainLookup.showAgain(key)) {
UserThread.runAfter(() -> {
new Popup().attention(Res.get("popup.attention.reasonForPaymentRuleChange")).
new Popup().attention(Res.get("popup.attention.newFeatureDuplicateOffer")).
dontShowAgainId(key)
.closeButtonText(Res.get("shared.iUnderstand"))
.show();
}, 1);
} else {
// If user add a fiat account later we don't show the popup as we assume it is a new user.
DontShowAgainLookup.dontShowAgain(key, true);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public void initialize() {
walletInfoTab.setText(Res.get("account.menu.walletInfo").toUpperCase());
backupTab.setText(Res.get("account.menu.backup").toUpperCase());

navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(AccountView.class) == 1) {
if (arbitratorRegistrationTab == null && viewPath.get(2).equals(ArbitratorRegistrationView.class)) {
navigation.navigateTo(MainView.class, AccountView.class, FiatAccountsView.class);
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/main/java/bisq/desktop/main/dao/DaoView.java
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public void initialize() {
root.getTabs().addAll(factsAndFiguresTab, bsqWalletTab, proposalsTab, bondingTab, burnBsqTab, monitorTab);
}

navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(DaoView.class) == 1) {
if (proposalsTab == null && viewPath.get(2).equals(EconomyView.class))
navigation.navigateTo(MainView.class, DaoView.class, EconomyView.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,19 +73,12 @@ private BondingView(CachingViewLoader viewLoader, Navigation navigation) {

@Override
public void initialize() {
listener = new Navigation.Listener() {
@Override
public void onNavigationRequested(ViewPath path) {
}

@Override
public void onNavigationRequested(ViewPath viewPath, @Nullable Object data) {
if (viewPath.size() != 4 || viewPath.indexOf(bisq.desktop.main.dao.bonding.BondingView.class) != 2)
return;

selectedViewClass = viewPath.tip();
loadView(selectedViewClass, data);
}
listener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(bisq.desktop.main.dao.bonding.BondingView.class) != 2)
return;

selectedViewClass = viewPath.tip();
loadView(selectedViewClass, data);
};

toggleGroup = new ToggleGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ private BurnBsqView(CachingViewLoader viewLoader, Navigation navigation) {

@Override
public void initialize() {
listener = viewPath -> {
listener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(BurnBsqView.class) != 2)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ private EconomyView(CachingViewLoader viewLoader, Navigation navigation) {

@Override
public void initialize() {
listener = viewPath -> {
listener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(EconomyView.class) != 2)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private GovernanceView(CachingViewLoader viewLoader, Navigation navigation, DaoF

@Override
public void initialize() {
navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(GovernanceView.class) != 2)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ private MonitorView(CachingViewLoader viewLoader, Navigation navigation) {

@Override
public void initialize() {
navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(MonitorView.class) != 2)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,12 @@ private BsqWalletView(CachingViewLoader viewLoader, Navigation navigation) {

@Override
public void initialize() {
listener = new Navigation.Listener() {
@Override
public void onNavigationRequested(ViewPath viewPath) {
if (viewPath.size() != 4 || viewPath.indexOf(BsqWalletView.class) != 2)
return;

selectedViewClass = viewPath.tip();
loadView(selectedViewClass);
}

@Override
public void onNavigationRequested(ViewPath viewPath, @Nullable Object data) {
if (viewPath.size() != 4 || viewPath.indexOf(BsqWalletView.class) != 2)
return;
listener = (viewPath, data) -> {
if (viewPath.size() != 4 || viewPath.indexOf(BsqWalletView.class) != 2)
return;

selectedViewClass = viewPath.tip();
loadView(selectedViewClass, data);
}
selectedViewClass = viewPath.tip();
loadView(selectedViewClass, data);
};

toggleGroup = new ToggleGroup();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public void initialize() {
lockedTab.setText(Res.get("funds.tab.locked").toUpperCase());
transactionsTab.setText(Res.get("funds.tab.transactions").toUpperCase());

navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(FundsView.class) == 1)
loadView(viewPath.tip());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ public void initialize() {
spreadTabPaymentMethod.setText(Res.get("market.tabs.spreadPayment").toUpperCase());
tradesTab.setText(Res.get("market.tabs.trades").toUpperCase());

navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(MarketView.class) == 1)
loadView(viewPath.tip());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext
private final BtcValidator btcValidator;
private final BsqValidator bsqValidator;
protected final SecurityDepositValidator securityDepositValidator;
private final PriceFeedService priceFeedService;
protected final PriceFeedService priceFeedService;
private final AccountAgeWitnessService accountAgeWitnessService;
private final Navigation navigation;
private final Preferences preferences;
Expand Down Expand Up @@ -179,7 +179,7 @@ public abstract class MutableOfferViewModel<M extends MutableOfferDataModel> ext

private ChangeListener<Boolean> isWalletFundedListener;
private ChangeListener<String> errorMessageListener;
private Offer offer;
protected Offer offer;
private Timer timeoutTimer;
private boolean inputIsMarketBasedPrice;
private ChangeListener<Boolean> useMarketBasedPriceListener;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ protected OfferView(ViewLoader viewLoader,

@Override
protected void initialize() {
navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(this.getClass()) == 1)
loadView(viewPath.tip());
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,16 @@
import bisq.desktop.common.view.CachingViewLoader;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.common.view.View;
import bisq.desktop.common.view.ViewLoader;
import bisq.desktop.main.MainView;
import bisq.desktop.main.portfolio.closedtrades.ClosedTradesView;
import bisq.desktop.main.portfolio.duplicateoffer.DuplicateOfferView;
import bisq.desktop.main.portfolio.editoffer.EditOfferView;
import bisq.desktop.main.portfolio.failedtrades.FailedTradesView;
import bisq.desktop.main.portfolio.openoffer.OpenOffersView;
import bisq.desktop.main.portfolio.pendingtrades.PendingTradesView;

import bisq.core.locale.Res;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OpenOffer;
import bisq.core.trade.Trade;
import bisq.core.trade.failed.FailedTradesManager;
Expand All @@ -48,22 +49,25 @@

import java.util.List;

import javax.annotation.Nullable;

@FxmlView
public class PortfolioView extends ActivatableView<TabPane, Void> {

@FXML
Tab openOffersTab, pendingTradesTab, closedTradesTab;
private Tab editOpenOfferTab;
private Tab editOpenOfferTab, duplicateOfferTab;
private final Tab failedTradesTab = new Tab(Res.get("portfolio.tab.failed").toUpperCase());
private Tab currentTab;
private Navigation.Listener navigationListener;
private ChangeListener<Tab> tabChangeListener;
private ListChangeListener<Tab> tabListChangeListener;

private final ViewLoader viewLoader;
private final CachingViewLoader viewLoader;
private final Navigation navigation;
private final FailedTradesManager failedTradesManager;
private EditOfferView editOfferView;
private DuplicateOfferView duplicateOfferView;
private boolean editOpenOfferViewOpen;
private OpenOffer openOffer;
private OpenOffersView openOffersView;
Expand All @@ -84,9 +88,9 @@ public void initialize() {
pendingTradesTab.setText(Res.get("portfolio.tab.pendingTrades").toUpperCase());
closedTradesTab.setText(Res.get("portfolio.tab.history").toUpperCase());

navigationListener = viewPath -> {
navigationListener = (viewPath, data) -> {
if (viewPath.size() == 3 && viewPath.indexOf(PortfolioView.class) == 1)
loadView(viewPath.tip());
loadView(viewPath.tip(), data);
};

tabChangeListener = (ov, oldValue, newValue) -> {
Expand All @@ -98,12 +102,16 @@ else if (newValue == closedTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, ClosedTradesView.class);
else if (newValue == failedTradesTab)
navigation.navigateTo(MainView.class, PortfolioView.class, FailedTradesView.class);
else if (newValue == editOpenOfferTab) {
else if (newValue == editOpenOfferTab)
navigation.navigateTo(MainView.class, PortfolioView.class, EditOfferView.class);
else if (newValue == duplicateOfferTab) {
navigation.navigateTo(MainView.class, PortfolioView.class, DuplicateOfferView.class);
}

if (oldValue != null && oldValue == editOpenOfferTab)
editOfferView.onTabSelected(false);
if (oldValue != null && oldValue == duplicateOfferTab)
duplicateOfferView.onTabSelected(false);

};

Expand All @@ -112,6 +120,8 @@ else if (newValue == editOpenOfferTab) {
List<? extends Tab> removedTabs = change.getRemoved();
if (removedTabs.size() == 1 && removedTabs.get(0).equals(editOpenOfferTab))
onEditOpenOfferRemoved();
if (removedTabs.size() == 1 && removedTabs.get(0).equals(duplicateOfferTab))
onDuplicateOfferRemoved();
};
}

Expand All @@ -125,6 +135,15 @@ private void onEditOpenOfferRemoved() {
navigation.navigateTo(MainView.class, this.getClass(), OpenOffersView.class);
}

private void onDuplicateOfferRemoved() {
if (duplicateOfferView != null) {
duplicateOfferView.onClose();
duplicateOfferView = null;
}

navigation.navigateTo(MainView.class, this.getClass(), OpenOffersView.class);
}

@Override
protected void activate() {
failedTradesManager.getObservableList().addListener((ListChangeListener<Trade>) c -> {
Expand All @@ -149,6 +168,9 @@ else if (root.getSelectionModel().getSelectedItem() == failedTradesTab)
else if (root.getSelectionModel().getSelectedItem() == editOpenOfferTab) {
navigation.navigateTo(MainView.class, PortfolioView.class, EditOfferView.class);
if (editOfferView != null) editOfferView.onTabSelected(true);
} else if (root.getSelectionModel().getSelectedItem() == duplicateOfferTab) {
navigation.navigateTo(MainView.class, PortfolioView.class, DuplicateOfferView.class);
if (duplicateOfferView != null) duplicateOfferView.onTabSelected(true);
}
}

Expand All @@ -160,7 +182,7 @@ protected void deactivate() {
currentTab = null;
}

private void loadView(Class<? extends View> viewClass) {
private void loadView(Class<? extends View> viewClass, @Nullable Object data) {
// we want to get activate/deactivate called, so we remove the old view on tab change
// TODO Don't understand the check for currentTab != editOpenOfferTab
if (currentTab != null && currentTab != editOpenOfferTab)
Expand Down Expand Up @@ -195,6 +217,26 @@ private void loadView(Class<? extends View> viewClass) {
view = viewLoader.load(OpenOffersView.class);
selectOpenOffersView((OpenOffersView) view);
}
} else if (view instanceof DuplicateOfferView) {
if (duplicateOfferView == null && data instanceof OfferPayload && data != null) {
viewLoader.removeFromCache(viewClass); // remove cached dialog
view = viewLoader.load(viewClass); // and load a fresh one
duplicateOfferView = (DuplicateOfferView) view;
duplicateOfferView.initWithData((OfferPayload) data);
duplicateOfferTab = new Tab(Res.get("portfolio.tab.duplicateOffer").toUpperCase());
duplicateOfferView.setCloseHandler(() -> {
root.getTabs().remove(duplicateOfferTab);
});
root.getTabs().add(duplicateOfferTab);
}
if (duplicateOfferView != null) {
if (currentTab != duplicateOfferTab)
duplicateOfferView.onTabSelected(true);
currentTab = duplicateOfferTab;
} else {
view = viewLoader.load(OpenOffersView.class);
selectOpenOffersView((OpenOffersView) view);
}
}

currentTab.setContent(view.getRoot());
Expand Down
Loading

0 comments on commit c17b46f

Please sign in to comment.