<commit_before>import {autobind, debounce} from 'core-decorators'
import {connect} from 'react-redux'
import {createElement, PropTypes, PureComponent} from 'react'
import _debounce from 'lodash/debounce'
import CSSModules from 'react-css-modules'

import {
  genBookmarkList,
  getBookmarkType,
  getFlatTree,
  getSearchResult,
  getSlicedTrees,
  isFolder,
  setPredefinedStyleSheet
} from '../functions'
import {
  removeTreeInfosFromIndex,
  replaceTreeInfoByIndex,
  updateEditorTarget,
  updateMenuTarget,
  updateKeyboardTarget,
  updateTrees
} from '../actions'
import {
  TYPE_ROOT_FOLDER
} from '../constants'
import Editor from '../components/Editor'
import Menu from '../components/Menu'
import MenuCover from '../components/MenuCover'
import Panel from '../components/Panel'

import styles from '../../../css/popup/app.css'

class App extends PureComponent {
  componentWillMount() {
    const {options} = this.props

    setPredefinedStyleSheet(options)
  }

  componentDidMount() {
    this.initBookmarkEvent()
  }

  getKeyboardTargetTreeIndex() {
    const {
      keyboardTarget,
      trees
    } = this.props

    if (!keyboardTarget) {
      return trees.length - 1
    }

    if (getBookmarkType(keyboardTarget) === TYPE_ROOT_FOLDER) {
      return 0
    }

    const matchedIndex = trees.findIndex((treeInfo) => treeInfo.id === keyboardTarget.parentId)

    if (matchedIndex < 0) {
      return trees.length - 1
    }

    return matchedIndex
  }

  handleContextMenu(evt) {
    // allow native context menu if it is an input element
    if (evt.target.tagName === 'INPUT') {
      return
    }

    // disable native context menu
    evt.preventDefault()
  }

  @autobind
  handleKeyDown(evt) {
    evt.persist()

    const {
      editorTarget,
      menuTarget
    } = this.props

    if (!editorTarget && !menuTarget) {
      // preventDefault here because default operation may run before debounced/async function
      switch (evt.keyCode) {
        case 9: // tab
        case 38: // up
        case 40: // down
          evt.preventDefault()
          break

        default:
      }

      this._handleKeyDown(evt)
    }
  }

  @debounce(30)
  async _handleKeyDown(evt) {
    switch (evt.keyCode) {
      case 9: // tab
        await this.keyboardArrowUpDownHandler(evt.shiftKey)
        break

      case 37: // left
        await this.keyboardArrowLeftRightHandler(true)
        break

      case 38: // up
        await this.keyboardArrowUpDownHandler(true)
        break

      case 39: // right
        await this.keyboardArrowLeftRightHandler(false)
        break

      case 40: // down
        await this.keyboardArrowUpDownHandler(false)
        break

      default:
    }
  }

  handleMouseDown(evt) {<commit_msg>Init keyCode that we will need to support<commit_after>import {autobind, debounce} from 'core-decorators'
import {connect} from 'react-redux'
import {createElement, PropTypes, PureComponent} from 'react'
import _debounce from 'lodash/debounce'
import CSSModules from 'react-css-modules'

import {
  genBookmarkList,
  getBookmarkType,
  getFlatTree,
  getSearchResult,
  getSlicedTrees,
  isFolder,
  setPredefinedStyleSheet
} from '../functions'
import {
  removeTreeInfosFromIndex,
  replaceTreeInfoByIndex,
  updateEditorTarget,
  updateMenuTarget,
  updateKeyboardTarget,
  updateTrees
} from '../actions'
import {
  TYPE_ROOT_FOLDER
} from '../constants'
import Editor from '../components/Editor'
import Menu from '../components/Menu'
import MenuCover from '../components/MenuCover'
import Panel from '../components/Panel'

import styles from '../../../css/popup/app.css'

class App extends PureComponent {
  componentWillMount() {
    const {options} = this.props

    setPredefinedStyleSheet(options)
  }

  componentDidMount() {
    this.initBookmarkEvent()
  }

  getKeyboardTargetTreeIndex() {
    const {
      keyboardTarget,
      trees
    } = this.props

    if (!keyboardTarget) {
      return trees.length - 1
    }

    if (getBookmarkType(keyboardTarget) === TYPE_ROOT_FOLDER) {
      return 0
    }

    const matchedIndex = trees.findIndex((treeInfo) => treeInfo.id === keyboardTarget.parentId)

    if (matchedIndex < 0) {
      return trees.length - 1
    }

    return matchedIndex
  }

  handleContextMenu(evt) {
    // allow native context menu if it is an input element
    if (evt.target.tagName === 'INPUT') {
      return
    }

    // disable native context menu
    evt.preventDefault()
  }

  @autobind
  handleKeyDown(evt) {
    evt.persist()

    const {
      editorTarget,
      menuTarget
    } = this.props

    if (!editorTarget && !menuTarget) {
      // preventDefault here because default operation may run before debounced/async function
      switch (evt.keyCode) {
        case 9: // tab
        case 38: // up
        case 40: // down
          evt.preventDefault()
          break

        default:
      }

      this._handleKeyDown(evt)
    }
  }

  @debounce(30)
  async _handleKeyDown(evt) {
    switch (evt.keyCode) {
      case 9: // tab
        await this.keyboardArrowUpDownHandler(evt.shiftKey)
        break

      case 13: // enter
        break

      case 37: // left
        await this.keyboardArrowLeftRightHandler(true)
        break

      case 38: // up
        await this.keyboardArrowUpDownHandler(true)
        break

      case 39: // right
        await this.keyboardArrowLeftRightHandler(false)
        break

      case 40: // down
        await this.keyboardArrowUpDownHandler(false)
        break

      case 91: // command
      case 93: // command
        break

      default:
    }
  }

  handleMouseDown(evt) {
{'fraction_non_alphanumeric': 0.09865391427559334, 'fraction_numerical': 0.008147360963513992, 'mean_word_length': 2.520573566084788, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, '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': '4869229', 'n_tokens_mistral': 1756, 'n_tokens_neox': 1711, 'n_words': 412}