<commit_before>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as DataGrid from '../data_grid/data_grid.js';
import * as SDK from '../sdk/sdk.js';  // eslint-disable-line no-unused-vars
import * as UI from '../ui/ui.js';

import {NetworkNode, NetworkRequestNode} from './NetworkDataGridNode.js';  // eslint-disable-line no-unused-vars
import {NetworkLogView} from './NetworkLogView.js';                        // eslint-disable-line no-unused-vars
import {NetworkManageCustomHeadersView} from './NetworkManageCustomHeadersView.js';
import {NetworkTimeCalculator, NetworkTransferDurationCalculator, NetworkTransferTimeCalculator,} from './NetworkTimeCalculator.js';  // eslint-disable-line no-unused-vars
import {NetworkWaterfallColumn} from './NetworkWaterfallColumn.js';
import {RequestInitiatorView} from './RequestInitiatorView.js';

/**
 * @unrestricted
 */
export class NetworkLogViewColumns {
  /**
   * @param {!NetworkLogView} networkLogView
   * @param {!NetworkTransferTimeCalculator} timeCalculator
   * @param {!NetworkTransferDurationCalculator} durationCalculator
   * @param {!Common.Settings.Setting} networkLogLargeRowsSetting
   */
  constructor(networkLogView, timeCalculator, durationCalculator, networkLogLargeRowsSetting) {
    this._networkLogView = networkLogView;

    /** @type {!Common.Settings.Setting} */
    this._persistantSettings = Common.Settings.Settings.instance().createSetting('networkLogColumns', {});

    this._networkLogLargeRowsSetting = networkLogLargeRowsSetting;
    this._networkLogLargeRowsSetting.addChangeListener(this._updateRowsSize, this);

    /** @type {!Map<string, !Array<number>>} */
    this._eventDividers = new Map();
    this._eventDividersShown = false;

    this._gridMode = true;

    /** @type {!Array.<!Descriptor>} */
    this._columns = [];

    this._waterfallRequestsAreStale = false;
    this._waterfallScrollerWidthIsStale = true;

    /** @type {!Components.Linkifier.Linkifier} */
    this._popupLinkifier = new Components.Linkifier.Linkifier();

    /** @type {!Map<string, !NetworkTimeCalculator>} */
    this._calculatorsMap = new Map();
    this._calculatorsMap.set(_calculatorTypes.Time, timeCalculator);
    this._calculatorsMap.set(_calculatorTypes.Duration, durationCalculator);

    this._lastWheelTime = 0;

    this._setupDataGrid();
    this._setupWaterfall();
  }

  /**
   * @param {!Descriptor} columnConfig
   * @return {!DataGrid.DataGrid.ColumnDescriptor}
   */
  static _convertToDataGridDescriptor(columnConfig) {
    return /** @type {!DataGrid.DataGrid.ColumnDescriptor} */ ({
      id: columnConfig.id,
      title: columnConfig.title,
      sortable: columnConfig.sortable,
      align: columnConfig.align,
      nonSelectable: columnConfig.nonSelectable,
      weight: columnConfig.weight,
      allowInSortByEvenWhenHidden: columnConfig.allowInSortByEvenWhenHidden,
    });
  }

  wasShown() {
    this._updateRowsSize();
  }

  willHide() {
    this._popoverHelper.hidePopover();
  }

  reset() {
    if (this._popoverHelper) {
      this._popoverHelper.hidePopover();
    }
    this._eventDividers.clear();
  }

  _setupDataGrid() {
    const defaultColumns = _defaultColumns;
    const defaultColumnConfig = _defaultColumnConfig;

    this._columns = /** @type {!Array<!Descriptor>} */ ([]);
    for (const currentConfigColumn of defaultColumns) {
      const descriptor = Object.assign({}, defaultColumnConfig, currentConfigColumn);
      const columnConfig = /** @type {!Descriptor} */ (descriptor);
      columnConfig.id = columnConfig.id;
      if (columnConfig.subtitle) {
        columnConfig.titleDOMFragment = this._makeHeaderFragment(columnConfig.title, columnConfig.subtitle);
      }
      this._columns.push(columnConfig);
    }
    this._loadCustomColumnsAndSettings();

    this._popoverHelper =
        new UI.PopoverHelper.PopoverHelper(this._networkLogView.element, this._getPopoverRequest.bind(this));
    this._popoverHelper.setHasPadding(true);
    this._popoverHelper.setTimeout(300, 300);

    /** @type {!DataGrid.SortableDataGrid.SortableDataGrid<!NetworkNode>} */
    this._dataGrid = new DataGrid.SortableDataGrid.SortableDataGrid(
        {displayName: ls`Network Log`, columns: this._columns.map(NetworkLogViewColumns._convertToDataGridDescriptor)});
    this._dataGrid.element.addEventListener('mousedown', event => {
      if (!this._dataGrid.selectedNode && event.button) {
        event.consume();
      }
    }, true);

    this._dataGridScroller = this._dataGrid.scrollContainer;

    this._updateColumns();
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortHandler, this);
    this._dataGrid.setHeaderContextMenuCallback(this._innerHeaderContextMenu.bind(this));

    this._activeWaterfallSortId = WaterfallSortIds.StartTime;
    this._dataGrid.markColumnAsSortedBy(_initialSortColumn, DataGrid.DataGrid.Order.Ascending);

    this._splitWidget = new UI.SplitWidget.SplitWidget(true, true, 'networkPanelSplitViewWaterfall', 200);
    const widget = this._dataGrid.asWidget();
    widget.setMinimumSize(150, 0);
    this._splitWidget.setMainWidget(widget);
  }

  _setupWaterfall() {
    this._waterfallColumn = new NetworkWaterfallColumn(this._networkLogView.calculator());

    this._waterfallColumn.element.addEventListener('contextmenu', handleContextMenu.bind(this));
    this._waterfallColumn.element.addEventListener('mousewheel', this._onMouseWheel.bind(this, false), {passive: true});
    this._dataGridScroller.addEventListener('mousewheel', this._onMouseWheel.bind(this, true), true);

    this._waterfallScroller = this._waterfallColumn.contentElement.createChild('div', 'network-waterfall-v-scroll');
    this._waterfallScrollerContent = this._waterfallScroller.createChild('div', 'network-waterfall-v-scroll-content');

    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.PaddingChanged, () => {
      this._waterfallScrollerWidthIsStale = true;
      this._syncScrollers();
    });
    this._dataGrid.addEventListener(
        DataGrid.ViewportDataGrid.Events.ViewportCalculated, this._redrawWaterfallColumn.bind(this));

    this._createWaterfallHeader();
    this._waterfallColumn.contentElement.classList.add('network-waterfall-view');

    this._waterfallColumn.setMinimumSize(100, 0);
    this._splitWidget.setSidebarWidget(this._waterfallColumn);

    this.switchViewMode(false);

    /**
     * @param {!Event} event
     * @this {NetworkLogViewColumns}
     */
    function handleContextMenu(event) {
      const node = this._waterfallColumn.getNodeFromPoint(event.offsetX, event.offsetY);
      if (!node) {
        return;
      }
      const request = node.request();
      if (!request) {
        return;
      }
      const contextMenu = new UI.ContextMenu.ContextMenu(event);
      this._networkLogView.handleContextMenuForRequest(contextMenu, request);
      contextMenu.show();
    }
  }

  /**
   * @param {boolean} shouldConsume
   * @param {!Event} event
   */
  _onMouseWheel(shouldConsume, event) {
    if (shouldConsume) {
      event.consume(true);
    }
    const hasRecentWheel = Date.now() - this._lastWheelTime < 80;
    this._activeScroller.scrollBy({top: -event.wheelDeltaY, behavior: hasRecentWheel ? 'instant' : 'smooth'});
    this._syncScrollers();
    this._lastWheelTime = Date.now();
  }

  _syncScrollers() {
    if (!this._waterfallColumn.isShowing()) {
      return;
    }
    this._waterfallScrollerContent.style.height = this._dataGridScroller.scrollHeight + 'px';
    this._updateScrollerWidthIfNeeded();
    this._dataGridScroller.scrollTop = this._waterfallScroller.scrollTop;
  }

  _updateScrollerWidthIfNeeded() {
    if (this._waterfallScrollerWidthIsStale) {
      this._waterfallScrollerWidthIsStale = false;
      this._waterfallColumn.setRightPadding(
          this._waterfallScroller.offsetWidth - this._waterfallScrollerContent.offsetWidth);
    }
  }

  _redrawWaterfallColumn() {
    if (!this._waterfallRequestsAreStale) {
      this._updateScrollerWidthIfNeeded();
      this._waterfallColumn.update(
          this._activeScroller.scrollTop, this._eventDividersShown ? this._eventDividers : undefined);
      return;
    }
    this._syncScrollers();
    const nodes = this._networkLogView.flatNodesList();
    this._waterfallColumn.update(this._activeScroller.scrollTop, this._eventDividers, nodes);<commit_msg>Add simple touch scroll support in the request list<commit_after>// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import * as Common from '../common/common.js';
import * as Components from '../components/components.js';
import * as DataGrid from '../data_grid/data_grid.js';
import * as SDK from '../sdk/sdk.js';  // eslint-disable-line no-unused-vars
import * as UI from '../ui/ui.js';

import {NetworkNode, NetworkRequestNode} from './NetworkDataGridNode.js';  // eslint-disable-line no-unused-vars
import {NetworkLogView} from './NetworkLogView.js';                        // eslint-disable-line no-unused-vars
import {NetworkManageCustomHeadersView} from './NetworkManageCustomHeadersView.js';
import {NetworkTimeCalculator, NetworkTransferDurationCalculator, NetworkTransferTimeCalculator,} from './NetworkTimeCalculator.js';  // eslint-disable-line no-unused-vars
import {NetworkWaterfallColumn} from './NetworkWaterfallColumn.js';
import {RequestInitiatorView} from './RequestInitiatorView.js';

/**
 * @unrestricted
 */
export class NetworkLogViewColumns {
  /**
   * @param {!NetworkLogView} networkLogView
   * @param {!NetworkTransferTimeCalculator} timeCalculator
   * @param {!NetworkTransferDurationCalculator} durationCalculator
   * @param {!Common.Settings.Setting} networkLogLargeRowsSetting
   */
  constructor(networkLogView, timeCalculator, durationCalculator, networkLogLargeRowsSetting) {
    this._networkLogView = networkLogView;

    /** @type {!Common.Settings.Setting} */
    this._persistantSettings = Common.Settings.Settings.instance().createSetting('networkLogColumns', {});

    this._networkLogLargeRowsSetting = networkLogLargeRowsSetting;
    this._networkLogLargeRowsSetting.addChangeListener(this._updateRowsSize, this);

    /** @type {!Map<string, !Array<number>>} */
    this._eventDividers = new Map();
    this._eventDividersShown = false;

    this._gridMode = true;

    /** @type {!Array.<!Descriptor>} */
    this._columns = [];

    this._waterfallRequestsAreStale = false;
    this._waterfallScrollerWidthIsStale = true;

    /** @type {!Components.Linkifier.Linkifier} */
    this._popupLinkifier = new Components.Linkifier.Linkifier();

    /** @type {!Map<string, !NetworkTimeCalculator>} */
    this._calculatorsMap = new Map();
    this._calculatorsMap.set(_calculatorTypes.Time, timeCalculator);
    this._calculatorsMap.set(_calculatorTypes.Duration, durationCalculator);

    this._lastWheelTime = 0;

    this._setupDataGrid();
    this._setupWaterfall();
  }

  /**
   * @param {!Descriptor} columnConfig
   * @return {!DataGrid.DataGrid.ColumnDescriptor}
   */
  static _convertToDataGridDescriptor(columnConfig) {
    return /** @type {!DataGrid.DataGrid.ColumnDescriptor} */ ({
      id: columnConfig.id,
      title: columnConfig.title,
      sortable: columnConfig.sortable,
      align: columnConfig.align,
      nonSelectable: columnConfig.nonSelectable,
      weight: columnConfig.weight,
      allowInSortByEvenWhenHidden: columnConfig.allowInSortByEvenWhenHidden,
    });
  }

  wasShown() {
    this._updateRowsSize();
  }

  willHide() {
    this._popoverHelper.hidePopover();
  }

  reset() {
    if (this._popoverHelper) {
      this._popoverHelper.hidePopover();
    }
    this._eventDividers.clear();
  }

  _setupDataGrid() {
    const defaultColumns = _defaultColumns;
    const defaultColumnConfig = _defaultColumnConfig;

    this._columns = /** @type {!Array<!Descriptor>} */ ([]);
    for (const currentConfigColumn of defaultColumns) {
      const descriptor = Object.assign({}, defaultColumnConfig, currentConfigColumn);
      const columnConfig = /** @type {!Descriptor} */ (descriptor);
      columnConfig.id = columnConfig.id;
      if (columnConfig.subtitle) {
        columnConfig.titleDOMFragment = this._makeHeaderFragment(columnConfig.title, columnConfig.subtitle);
      }
      this._columns.push(columnConfig);
    }
    this._loadCustomColumnsAndSettings();

    this._popoverHelper =
        new UI.PopoverHelper.PopoverHelper(this._networkLogView.element, this._getPopoverRequest.bind(this));
    this._popoverHelper.setHasPadding(true);
    this._popoverHelper.setTimeout(300, 300);

    /** @type {!DataGrid.SortableDataGrid.SortableDataGrid<!NetworkNode>} */
    this._dataGrid = new DataGrid.SortableDataGrid.SortableDataGrid(
        {displayName: ls`Network Log`, columns: this._columns.map(NetworkLogViewColumns._convertToDataGridDescriptor)});
    this._dataGrid.element.addEventListener('mousedown', event => {
      if (!this._dataGrid.selectedNode && event.button) {
        event.consume();
      }
    }, true);

    this._dataGridScroller = this._dataGrid.scrollContainer;

    this._updateColumns();
    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.SortingChanged, this._sortHandler, this);
    this._dataGrid.setHeaderContextMenuCallback(this._innerHeaderContextMenu.bind(this));

    this._activeWaterfallSortId = WaterfallSortIds.StartTime;
    this._dataGrid.markColumnAsSortedBy(_initialSortColumn, DataGrid.DataGrid.Order.Ascending);

    this._splitWidget = new UI.SplitWidget.SplitWidget(true, true, 'networkPanelSplitViewWaterfall', 200);
    const widget = this._dataGrid.asWidget();
    widget.setMinimumSize(150, 0);
    this._splitWidget.setMainWidget(widget);
  }

  _setupWaterfall() {
    this._waterfallColumn = new NetworkWaterfallColumn(this._networkLogView.calculator());

    this._waterfallColumn.element.addEventListener('contextmenu', handleContextMenu.bind(this));
    this._waterfallColumn.element.addEventListener('mousewheel', this._onMouseWheel.bind(this, false), {passive: true});
    this._waterfallColumn.element.addEventListener('touchstart', this._onTouchStart.bind(this));
    this._waterfallColumn.element.addEventListener('touchmove', this._onTouchMove.bind(this));
    this._waterfallColumn.element.addEventListener('touchend', this._onTouchEnd.bind(this));

    this._dataGridScroller.addEventListener('mousewheel', this._onMouseWheel.bind(this, true), true);
    this._dataGridScroller.addEventListener('touchstart', this._onTouchStart.bind(this));
    this._dataGridScroller.addEventListener('touchmove', this._onTouchMove.bind(this));
    this._dataGridScroller.addEventListener('touchend', this._onTouchEnd.bind(this));

    this._waterfallScroller = this._waterfallColumn.contentElement.createChild('div', 'network-waterfall-v-scroll');
    this._waterfallScrollerContent = this._waterfallScroller.createChild('div', 'network-waterfall-v-scroll-content');

    this._dataGrid.addEventListener(DataGrid.DataGrid.Events.PaddingChanged, () => {
      this._waterfallScrollerWidthIsStale = true;
      this._syncScrollers();
    });
    this._dataGrid.addEventListener(
        DataGrid.ViewportDataGrid.Events.ViewportCalculated, this._redrawWaterfallColumn.bind(this));

    this._createWaterfallHeader();
    this._waterfallColumn.contentElement.classList.add('network-waterfall-view');

    this._waterfallColumn.setMinimumSize(100, 0);
    this._splitWidget.setSidebarWidget(this._waterfallColumn);

    this.switchViewMode(false);

    /**
     * @param {!Event} event
     * @this {NetworkLogViewColumns}
     */
    function handleContextMenu(event) {
      const node = this._waterfallColumn.getNodeFromPoint(event.offsetX, event.offsetY);
      if (!node) {
        return;
      }
      const request = node.request();
      if (!request) {
        return;
      }
      const contextMenu = new UI.ContextMenu.ContextMenu(event);
      this._networkLogView.handleContextMenuForRequest(contextMenu, request);
      contextMenu.show();
    }
  }

  /**
   * @param {boolean} shouldConsume
   * @param {!Event} event
   */
  _onMouseWheel(shouldConsume, event) {
    if (shouldConsume) {
      event.consume(true);
    }
    const hasRecentWheel = Date.now() - this._lastWheelTime < 80;
    this._activeScroller.scrollBy({top: -event.wheelDeltaY, behavior: hasRecentWheel ? 'instant' : 'smooth'});
    this._syncScrollers();
    this._lastWheelTime = Date.now();
  }

  /**
   * @param {!Event} event
   */
  _onTouchStart(event) {
    this._hasScrollerTouchStarted = true;
    this._scrollerTouchStartPos = event.changedTouches[0].pageY;
  }

  /**
   * @param {!Event} event
   */
  _onTouchMove(event) {
    if (!this._hasScrollerTouchStarted) {
      return;
    }

    const currentPos = event.changedTouches[0].pageY;
    const delta = this._scrollerTouchStartPos - currentPos;

    this._activeScroller.scrollBy({top: delta, behavior: 'instant'});
    this._syncScrollers();

    this._scrollerTouchStartPos = currentPos;
  }

  _onTouchEnd() {
    this._hasScrollerTouchStarted = false;
  }

  _syncScrollers() {
    if (!this._waterfallColumn.isShowing()) {
      return;
    }
    this._waterfallScrollerContent.style.height = this._dataGridScroller.scrollHeight + 'px';
    this._updateScrollerWidthIfNeeded();
    this._dataGridScroller.scrollTop = this._waterfallScroller.scrollTop;
  }

  _updateScrollerWidthIfNeeded() {
    if (this._waterfallScrollerWidthIsStale) {
      this._waterfallScrollerWidthIsStale = false;
      this._waterfallColumn.setRightPadding(
          this._waterfallScroller.offsetWidth - this._waterfallScrollerContent.offsetWidth);
    }
  }

  _redrawWaterfallColumn() {
    if (!this._waterfallRequestsAreStale) {
      this._updateScrollerWidthIfNeeded();
      this._waterfallColumn.update(
          this._activeScroller.scrollTop, this._eventDividersShown ? this._eventDividers : undefined);
      return;
    }
    this._syncScrollers();
    const nodes = this._networkLogView.flatNodesList();
    this._waterfallColumn.update(this._activeScroller.scrollTop, this._eventDividers, nodes);
{'fraction_non_alphanumeric': 0.12102463909692826, 'fraction_numerical': 0.0027135569304244005, 'mean_word_length': 4.164517937219731, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '515938', 'n_tokens_mistral': 5518, 'n_tokens_neox': 5341, 'n_words': 829}