/* * This file is part of Bitsquare. * * Bitsquare is free software: you can redistribute it and/or modify it * under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * Bitsquare is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public * License for more details. * * You should have received a copy of the GNU Affero General Public License * along with Bitsquare. If not, see <http://www.gnu.org/licenses/>. */ package io.bitsquare.gui.main.disputes; import io.bitsquare.app.DevFlags; import io.bitsquare.arbitration.Arbitrator; import io.bitsquare.arbitration.ArbitratorManager; import io.bitsquare.arbitration.DisputeManager; import io.bitsquare.common.crypto.KeyRing; import io.bitsquare.gui.Navigation; import io.bitsquare.gui.common.model.Activatable; import io.bitsquare.gui.common.view.*; import io.bitsquare.gui.main.MainView; import io.bitsquare.gui.main.disputes.arbitrator.ArbitratorDisputeView; import io.bitsquare.gui.main.disputes.trader.TraderDisputeView; import io.bitsquare.gui.main.overlays.popups.Popup; import io.bitsquare.gui.main.portfolio.PortfolioView; import io.bitsquare.gui.main.portfolio.pendingtrades.PendingTradesView; import io.bitsquare.p2p.NodeAddress; import io.bitsquare.user.Preferences; import javafx.beans.value.ChangeListener; import javafx.collections.MapChangeListener; import javafx.fxml.FXML; import javafx.scene.control.Tab; import javafx.scene.control.TabPane; import javax.inject.Inject; // will be probably only used for arbitration communication, will be renamed and the icon changed @FxmlView public class DisputesView extends ActivatableViewAndModel<TabPane, Activatable> { @FXML Tab tradersDisputesTab; private Tab arbitratorsDisputesTab; private final Navigation navigation; private final ArbitratorManager arbitratorManager; private DisputeManager disputeManager; private final KeyRing keyRing; private Preferences preferences; private Navigation.Listener navigationListener; private ChangeListener<Tab> tabChangeListener; private Tab currentTab; private final ViewLoader viewLoader; private MapChangeListener<NodeAddress, Arbitrator> arbitratorMapChangeListener; @Inject public DisputesView(CachingViewLoader viewLoader, Navigation navigation, ArbitratorManager arbitratorManager, DisputeManager disputeManager, KeyRing keyRing, Preferences preferences) { this.viewLoader = viewLoader; this.navigation = navigation; this.arbitratorManager = arbitratorManager; this.disputeManager = disputeManager; this.keyRing = keyRing; this.preferences = preferences; } @Override public void initialize() { log.debug("initialize "); navigationListener = viewPath -> { if (viewPath.size() == 3 && viewPath.indexOf(DisputesView.class) == 1) loadView(viewPath.tip()); }; tabChangeListener = (ov, oldValue, newValue) -> { if (newValue == tradersDisputesTab) navigation.navigateTo(MainView.class, DisputesView.class, TraderDisputeView.class); else if (newValue == arbitratorsDisputesTab) navigation.navigateTo(MainView.class, DisputesView.class, ArbitratorDisputeView.class); }; arbitratorMapChangeListener = change -> updateArbitratorsDisputesTabDisableState(); } private void updateArbitratorsDisputesTabDisableState() { boolean isActiveArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream() .filter(e -> e.getPubKeyRing() != null && e.getPubKeyRing().equals(keyRing.getPubKeyRing())) .findAny().isPresent(); boolean hasDisputesAsArbitrator = disputeManager.getDisputesAsObservableList().stream() .filter(d -> d.getArbitratorPubKeyRing().equals(keyRing.getPubKeyRing())) .findAny().isPresent(); if (arbitratorsDisputesTab == null && (isActiveArbitrator || hasDisputesAsArbitrator)) { arbitratorsDisputesTab = new Tab("Arbitrator's support tickets"); arbitratorsDisputesTab.setClosable(false); root.getTabs().add(arbitratorsDisputesTab); tradersDisputesTab.setText("Trader's support tickets"); } } @Override protected void activate() { arbitratorManager.updateArbitratorMap(); arbitratorManager.getArbitratorsObservableMap().addListener(arbitratorMapChangeListener); updateArbitratorsDisputesTabDisableState(); root.getSelectionModel().selectedItemProperty().addListener(tabChangeListener); navigation.addListener(navigationListener); if (arbitratorsDisputesTab != null && root.getSelectionModel().getSelectedItem() == arbitratorsDisputesTab) navigation.navigateTo(MainView.class, DisputesView.class, ArbitratorDisputeView.class); else navigation.navigateTo(MainView.class, DisputesView.class, TraderDisputeView.class); String key = "supportInfo"; if (!DevFlags.DEV_MODE) new Popup().backgroundInfo("Bitsquare is not a company and not operating any kind of customer support.\n\n" + "If there are disputes in the trade process (e.g. one trader does not follow the trade protocol) " + "the application will display a \"Open dispute\" button after the trade period is over " + "for contacting the arbitrator.\n" + "In cases of software bugs or network problems, which are detected by the application there will " + "be displayed a \"Open support ticket\" button to contact the arbitrator who will forward the issue " + "to the developers.\n\n" + "In cases where a user got stuck by a bug without getting displayed that \"Open support ticket\" button, " + "you can open a support ticket manually with a special short cut.\n\n" + "Please use that only if you are sure that the software is not working like expected. " + "If you have problems how to use Bitsquare or any questions please review the FAQ at the " + "Bitsquare.io web page or contact the Bitsquare team using " + "any of the communication channels offered " + "at the Bitsquare.io web page. The Bitsquare forum has a support section as well.\n\n" + "If you are sure you want to open a support ticket please select the trade which causes the problem " + "under \"Portfolio/Open trades\" and type the key combination \"cmd + o\" or \"crtl + o\" to open " + "the support ticket.") .actionButtonText("Go to \"Open trades\"") .onAction(() -> navigation.navigateTo(MainView.class, PortfolioView.class, PendingTradesView.class)) .dontShowAgainId(key, preferences) .show(); } @Override protected void deactivate() { arbitratorManager.getArbitratorsObservableMap().removeListener(arbitratorMapChangeListener); root.getSelectionModel().selectedItemProperty().removeListener(tabChangeListener); navigation.removeListener(navigationListener); currentTab = null; } private void loadView(Class<? extends View> viewClass) { // we want to get activate/deactivate called, so we remove the old view on tab change if (currentTab != null) currentTab.setContent(null); View view = viewLoader.load(viewClass); if (arbitratorsDisputesTab != null && view instanceof ArbitratorDisputeView) currentTab = arbitratorsDisputesTab; else currentTab = tradersDisputesTab; currentTab.setContent(view.getRoot()); root.getSelectionModel().select(currentTab); } }