<commit_before>import React from "react";
import {PropTypes} from "react";
import MarketsActions from "actions/MarketsActions";
import { MyOpenOrders } from "./MyOpenOrders";
import OrderBook from "./OrderBook";
import MarketHistory from "./MarketHistory";
import MyMarkets from "./MyMarkets";
import BuySell from "./BuySell";
import utils from "common/utils";
import PriceChartD3 from "./PriceChartD3";
import assetUtils from "common/asset_utils";
import DepthHighChart from "./DepthHighChart";
import { debounce, cloneDeep } from "lodash";
import BorrowModal from "../Modal/BorrowModal";
import notify from "actions/NotificationActions";
import AccountNotifications from "../Notifier/NotifierContainer";
import Ps from "perfect-scrollbar";
import { ChainStore, FetchChain } from "bitsharesjs/es";
import SettingsActions from "actions/SettingsActions";
import cnames from "classnames";
import market_utils from "common/market_utils";
import {Asset, Price, LimitOrderCreate} from "common/MarketClasses";
import ConfirmOrderModal from "./ConfirmOrderModal";
// import IndicatorModal from "./IndicatorModal";
import OpenSettleOrders from "./OpenSettleOrders";
import Highcharts from "highcharts/highstock";
import ExchangeHeader from "./ExchangeHeader";
import Translate from "react-translate-component";
import { Apis } from "bitsharesjs-ws";
import GatewayActions from "actions/GatewayActions";
import { checkFeeStatusAsync } from "common/trxHelper";

Highcharts.setOptions({
    global: {
        useUTC: false
    }
});

class Exchange extends React.Component {
    static propTypes = {
        marketCallOrders: PropTypes.object.isRequired,
        activeMarketHistory: PropTypes.object.isRequired,
        viewSettings: PropTypes.object.isRequired,
        priceData: PropTypes.array.isRequired,
        volumeData: PropTypes.array.isRequired
    };

    static defaultProps = {
        marketCallOrders: [],
        activeMarketHistory: {},
        viewSettings: {},
        priceData: [],
        volumeData: []
    };

    constructor(props) {
        super();

        this.state = this._initialState(props);

        this._getWindowSize = debounce(this._getWindowSize.bind(this), 150);
        this._checkFeeStatus = this._checkFeeStatus.bind(this);
        this.psInit = true;
    }

    _initialState(props) {
        let ws = props.viewSettings;
        let bid = {
            forSaleText: "",
            toReceiveText: "",
            priceText: "",
            for_sale: new Asset({
                asset_id: props.baseAsset.get("id"),
                precision: props.baseAsset.get("precision")
            }),
            to_receive: new Asset({
                asset_id: props.quoteAsset.get("id"),
                precision: props.quoteAsset.get("precision")
            })
        };
        bid.price = new Price({base: bid.for_sale, quote: bid.to_receive});
        let ask = {
            forSaleText: "",
            toReceiveText: "",
            priceText: "",
            for_sale: new Asset({
                asset_id: props.quoteAsset.get("id"),
                precision: props.quoteAsset.get("precision")
            }),
            to_receive: new Asset({
                asset_id: props.baseAsset.get("id"),
                precision: props.baseAsset.get("precision")
            })
        };
        ask.price = new Price({base: ask.for_sale, quote: ask.to_receive});

        /* Make sure the indicators objects only contains the current indicators */
        let savedIndicators = ws.get("indicators", {});
        let indicators = {};
        [["sma", true], ["ema1", false], ["ema2", false], ["smaVolume", true], ["macd", false], ["bb", false]].forEach(i => {
            indicators[i[0]] = (i[0] in savedIndicators) ? savedIndicators[i[0]] : i[1];
        });

        let savedIndicatorsSettings = ws.get("indicatorSettings", {});
        let indicatorSettings = {};
        [["sma", 7], ["ema1", 20], ["ema2", 50], ["smaVolume", 30]].forEach(i => {
            indicatorSettings[i[0]] = (i[0] in savedIndicatorsSettings) ?  savedIndicatorsSettings[i[0]] : i[1];
        });

        return {
            history: [],
            buySellOpen: ws.get("buySellOpen", true),
            bid,
            ask,
            flipBuySell: ws.get("flipBuySell", false),
            favorite: false,
            showDepthChart: ws.get("showDepthChart", false),
            leftOrderBook: ws.get("leftOrderBook", false),
            buyDiff: false,
            sellDiff: false,
            indicators,
            buySellTop: ws.get("buySellTop", true),
            buyFeeAssetIdx: ws.get("buyFeeAssetIdx", 0),
            sellFeeAssetIdx: ws.get("sellFeeAssetIdx", 0),
            indicatorSettings,
            tools: {
                fib: false,
                trendline: false
            },
            height: window.innerHeight,
            width: window.innerWidth,
            chartHeight: ws.get("chartHeight", 425),
            currentPeriod: ws.get("currentPeriod", 3600* 24 * 30 * 3) // 3 months
        };
    }

    _getLastMarketKey() {
        const chainID = Apis.instance().chain_id;
        return `lastMarket${chainID ? ("_" + chainID.substr(0, 8)) : ""}`;
    }

    componentWillMount() {
        if (Apis.instance().chain_id.substr(0, 8)=== "4018d784") {
            GatewayActions.fetchCoins.defer();
            GatewayActions.fetchBridgeCoins.defer();
        }

        this._checkFeeStatus();
    }

    componentDidMount() {
        SettingsActions.changeViewSetting.defer({
            [this._getLastMarketKey()]: this.props.quoteAsset.get("symbol") + "_" + this.props.baseAsset.get("symbol")
        });

        window.addEventListener("resize", this._getWindowSize, {capture: false, passive: true});
    }

    shouldComponentUpdate(nextProps) {
        if (!nextProps.marketReady && !this.props.marketReady) {
            return false;
        }
        return true;
    };

    _checkFeeStatus(assets = [this.props.coreAsset, this.props.baseAsset, this.props.quoteAsset], account = this.props.currentAccount) {
        let feeStatus = {};
        let p = [];
        assets.forEach(a => {
            p.push(checkFeeStatusAsync({accountID: account.get("id"), feeID: a.get("id"), type: "limit_order_create"}));
        });
        Promise.all(p).then(status => {
            assets.forEach((a, idx) => {
                feeStatus[a.get("id")] = status[idx];
            });
            if (!utils.are_equal_shallow(this.state.feeStatus, feeStatus)) {
                this.setState({
                    feeStatus
                });
            }
        });
    }

    _getWindowSize() {
        let { innerHeight, innerWidth } = window;
        if (innerHeight !== this.state.height || innerWidth !== this.state.width) {
            this.setState({
                height: innerHeight,
                width: innerWidth
            });
            let centerContainer = this.refs.center;
            if (centerContainer) {
                Ps.update(centerContainer);
            }
        }
    }

    componentWillReceiveProps(nextProps) {
        if (this.refs.center && this.psInit) {
            let centerContainer = this.refs.center;
            if (centerContainer) {
                Ps.initialize(centerContainer);
                this.psInit = false;
            }
        }
        if (
            nextProps.quoteAsset !== this.props.quoteAsset ||<commit_msg>Fix for exchange scrollbar not being initalized in some cases<commit_after>import React from "react";
import {PropTypes} from "react";
import MarketsActions from "actions/MarketsActions";
import { MyOpenOrders } from "./MyOpenOrders";
import OrderBook from "./OrderBook";
import MarketHistory from "./MarketHistory";
import MyMarkets from "./MyMarkets";
import BuySell from "./BuySell";
import utils from "common/utils";
import PriceChartD3 from "./PriceChartD3";
import assetUtils from "common/asset_utils";
import DepthHighChart from "./DepthHighChart";
import { debounce, cloneDeep } from "lodash";
import BorrowModal from "../Modal/BorrowModal";
import notify from "actions/NotificationActions";
import AccountNotifications from "../Notifier/NotifierContainer";
import Ps from "perfect-scrollbar";
import { ChainStore, FetchChain } from "bitsharesjs/es";
import SettingsActions from "actions/SettingsActions";
import cnames from "classnames";
import market_utils from "common/market_utils";
import {Asset, Price, LimitOrderCreate} from "common/MarketClasses";
import ConfirmOrderModal from "./ConfirmOrderModal";
// import IndicatorModal from "./IndicatorModal";
import OpenSettleOrders from "./OpenSettleOrders";
import Highcharts from "highcharts/highstock";
import ExchangeHeader from "./ExchangeHeader";
import Translate from "react-translate-component";
import { Apis } from "bitsharesjs-ws";
import GatewayActions from "actions/GatewayActions";
import { checkFeeStatusAsync } from "common/trxHelper";

Highcharts.setOptions({
    global: {
        useUTC: false
    }
});

class Exchange extends React.Component {
    static propTypes = {
        marketCallOrders: PropTypes.object.isRequired,
        activeMarketHistory: PropTypes.object.isRequired,
        viewSettings: PropTypes.object.isRequired,
        priceData: PropTypes.array.isRequired,
        volumeData: PropTypes.array.isRequired
    };

    static defaultProps = {
        marketCallOrders: [],
        activeMarketHistory: {},
        viewSettings: {},
        priceData: [],
        volumeData: []
    };

    constructor(props) {
        super();

        this.state = this._initialState(props);

        this._getWindowSize = debounce(this._getWindowSize.bind(this), 150);
        this._checkFeeStatus = this._checkFeeStatus.bind(this);
        this.psInit = true;
    }

    _initialState(props) {
        let ws = props.viewSettings;
        let bid = {
            forSaleText: "",
            toReceiveText: "",
            priceText: "",
            for_sale: new Asset({
                asset_id: props.baseAsset.get("id"),
                precision: props.baseAsset.get("precision")
            }),
            to_receive: new Asset({
                asset_id: props.quoteAsset.get("id"),
                precision: props.quoteAsset.get("precision")
            })
        };
        bid.price = new Price({base: bid.for_sale, quote: bid.to_receive});
        let ask = {
            forSaleText: "",
            toReceiveText: "",
            priceText: "",
            for_sale: new Asset({
                asset_id: props.quoteAsset.get("id"),
                precision: props.quoteAsset.get("precision")
            }),
            to_receive: new Asset({
                asset_id: props.baseAsset.get("id"),
                precision: props.baseAsset.get("precision")
            })
        };
        ask.price = new Price({base: ask.for_sale, quote: ask.to_receive});

        /* Make sure the indicators objects only contains the current indicators */
        let savedIndicators = ws.get("indicators", {});
        let indicators = {};
        [["sma", true], ["ema1", false], ["ema2", false], ["smaVolume", true], ["macd", false], ["bb", false]].forEach(i => {
            indicators[i[0]] = (i[0] in savedIndicators) ? savedIndicators[i[0]] : i[1];
        });

        let savedIndicatorsSettings = ws.get("indicatorSettings", {});
        let indicatorSettings = {};
        [["sma", 7], ["ema1", 20], ["ema2", 50], ["smaVolume", 30]].forEach(i => {
            indicatorSettings[i[0]] = (i[0] in savedIndicatorsSettings) ?  savedIndicatorsSettings[i[0]] : i[1];
        });

        return {
            history: [],
            buySellOpen: ws.get("buySellOpen", true),
            bid,
            ask,
            flipBuySell: ws.get("flipBuySell", false),
            favorite: false,
            showDepthChart: ws.get("showDepthChart", false),
            leftOrderBook: ws.get("leftOrderBook", false),
            buyDiff: false,
            sellDiff: false,
            indicators,
            buySellTop: ws.get("buySellTop", true),
            buyFeeAssetIdx: ws.get("buyFeeAssetIdx", 0),
            sellFeeAssetIdx: ws.get("sellFeeAssetIdx", 0),
            indicatorSettings,
            tools: {
                fib: false,
                trendline: false
            },
            height: window.innerHeight,
            width: window.innerWidth,
            chartHeight: ws.get("chartHeight", 425),
            currentPeriod: ws.get("currentPeriod", 3600* 24 * 30 * 3) // 3 months
        };
    }

    _getLastMarketKey() {
        const chainID = Apis.instance().chain_id;
        return `lastMarket${chainID ? ("_" + chainID.substr(0, 8)) : ""}`;
    }

    componentWillMount() {
        if (Apis.instance().chain_id.substr(0, 8)=== "4018d784") {
            GatewayActions.fetchCoins.defer();
            GatewayActions.fetchBridgeCoins.defer();
        }

        this._checkFeeStatus();
    }

    componentDidMount() {
        SettingsActions.changeViewSetting.defer({
            [this._getLastMarketKey()]: this.props.quoteAsset.get("symbol") + "_" + this.props.baseAsset.get("symbol")
        });

        window.addEventListener("resize", this._getWindowSize, {capture: false, passive: true});
    }

    shouldComponentUpdate(nextProps) {
        if (!nextProps.marketReady && !this.props.marketReady) {
            return false;
        }
        return true;
    };

    _checkFeeStatus(assets = [this.props.coreAsset, this.props.baseAsset, this.props.quoteAsset], account = this.props.currentAccount) {
        let feeStatus = {};
        let p = [];
        assets.forEach(a => {
            p.push(checkFeeStatusAsync({accountID: account.get("id"), feeID: a.get("id"), type: "limit_order_create"}));
        });
        Promise.all(p).then(status => {
            assets.forEach((a, idx) => {
                feeStatus[a.get("id")] = status[idx];
            });
            if (!utils.are_equal_shallow(this.state.feeStatus, feeStatus)) {
                this.setState({
                    feeStatus
                });
            }
        });
    }

    _getWindowSize() {
        let { innerHeight, innerWidth } = window;
        if (innerHeight !== this.state.height || innerWidth !== this.state.width) {
            this.setState({
                height: innerHeight,
                width: innerWidth
            });
            let centerContainer = this.refs.center;
            if (centerContainer) {
                Ps.update(centerContainer);
            }
        }
    }

    componentDidUpdate() {
        this._initPsContainer();
    }

    _initPsContainer() {
        if (this.refs.center && this.psInit) {
            let centerContainer = this.refs.center;
            if (centerContainer) {
                Ps.initialize(centerContainer);
                this.psInit = false;
            }
        }
    }

    componentWillReceiveProps(nextProps) {
        this._initPsContainer();
        if (
            nextProps.quoteAsset !== this.props.quoteAsset ||
{'fraction_non_alphanumeric': 0.1301460823373174, 'fraction_numerical': 0.006640106241699867, 'mean_word_length': 2.25995670995671, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7571529', 'n_tokens_mistral': 4364, 'n_tokens_neox': 4133, 'n_words': 859}