<commit_before>import React, { Component } from 'react'
import { ipcRenderer } from 'electron'
import { connect } from 'react-redux'
import cx from 'classnames'
import pathModule from 'path'
import SplitPane from 'react-split-pane'
import FaFolder from 'react-icons/fa/folder'
import IconClose from 'react-icons/md/close'
import IconEdit from 'react-icons/md/mode-edit'

import { openModal } from 'reducers/modals'

import { readDir, sortFiles, fsRename } from 'helpers/fs'
import { setPreview } from 'actions/preview'
import { updateSettings } from 'actions/settings'

import FileEditor from 'components/FileEditor'
import FilePreview from './FilePreview'
import OldSyntaxDetected from './OldSyntaxDetected'

import './styles.scss'

function renameFile(path, oldName, newName, files) {
  if (oldName === newName) {
    return
  }
  const filesWithoutOld = files.filter(f => f.name !== oldName)
  const fileExists = filesWithoutOld.some(f => f.name === newName)
  if (fileExists) {
    throw new Error('File already exists')
  }
  const oldFullName = pathModule.join(path, oldName)
  const newFullName = pathModule.join(path, newName)
  return fsRename(oldFullName, newFullName)
}

@connect(
  state => ({
    previewSize: state.settings.get('previewSize'),
  }),
  {
    setPreview,
    openModal,
    updateSettings,
  },
  null,
  { withRef: true },
)
class FilesList extends Component {
  state = {
    isAdding: false,
    files: [],
    isDragging: false,
    renamedFile: null,
    newName: '',
    isOldSyntaxDetected: false,
  }

  componentWillMount() {
    this._hasFocused = false
  }

  componentDidMount() {
    this.refresh()
    ipcRenderer.on('browser-window-focus', this.refresh)
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.path !== this.props.path) {
      this.refresh()
    }
    if (!prevState.isAdding && this.state.isAdding) {
      this._inputName.focus()
    }
    if (this.state.files.length > prevState.files.length && this._lastCreated) {
      this._refs[this._lastCreated].focus()
    }
    if (!prevState.renamedFile && this.state.renamedFile) {
      this._renameInput.select()
    }
  }

  componentWillUnmount() {
    this._unmounted = true
    ipcRenderer.removeListener('browser-window-focus', this.refresh)
  }

  handleDetectOldSyntax = () => this.setState({ isOldSyntaxDetected: true })

  handleSubmit = e => {
    e.preventDefault()
    const { path, onAddFile, onActiveFileChange } = this.props
    let name = this._inputName.value
    if (!name) {
      return
    }
    name = `${name}.mjml`
    const fileName = pathModule.join(path, name)
    onAddFile(fileName)
    onActiveFileChange({
      isFolder: false,
      name,
    })
    this._lastCreated = name
    this.toggleAdding()
  }

  handleClickFactory = f => () => {
    const p = pathModule.join(this.props.path, f.name)
    if (f.isFolder) {
      return this.props.onPathChange(p)
    }
    if (this.props.onFileClick) {
      this.props.onFileClick(p)
    }
    // preview will be set by the onChange on editor
    // no need to trigger it here
    if (!p.endsWith('.mjml')) {
      this.props.setPreview(p)
    }
    this.props.onActiveFileChange(f)
  }

  handleClickDirectFactory = (items, i) => () => {
    const sub = items.slice(0, i + 1)
    const relativePath = sub.join(pathModule.sep)
    const path = pathModule.join(this.props.rootPath, relativePath)
    this.props.onPathChange(path)
  }

  handleRemoveFileFactory = f => e => {
    if (e) {
      e.preventDefault()
    }
    const p = pathModule.join(this.props.path, f.name)
    this.props.onRemoveFile(p)
  }

  handleNavigateUp = () => {
    this.props.onPathChange(pathModule.dirname(this.props.path))
  }

  handlePreviewPanelStopDrag = size => {
    this.setCurrentSize(size)
    this.stopDrag()
  }

  handleChangeNewName = e => {
    this.setState({ newName: e.target.value })
  }

  handleCancelRename = () =>
    this.setState({
      renamedFile: null,
      newName: '',
    })

  handleRenameInputKeyDown = async e => {
    switch (
      e.which // eslint-disable-line
    ) {
      case 27:
        this.handleCancelRename()
        break
      case 13:
        try {
          const { path } = this.props
          const { newName, renamedFile, files } = this.state
          await renameFile(path, renamedFile.name, newName, files)
          const newFile = { name: newName, isFolder: false }
          const newFiles = files.map(f => {
            if (f === renamedFile) {
              return newFile
            }
            return f
          })
          sortFiles(newFiles)
          this.setState({ files: newFiles })
          this.props.onActiveFileChange(newFile)
          this.handleCancelRename()
        } catch (e) {} // eslint-disable-line
        break
    }
  }

  handleMigrate = () => {
    this._editor.migrateToMJML4()
    this.setState({ isOldSyntaxDetected: false })
  }

  setCurrentSize = size => {
    this.props.updateSettings(settings => {
      return settings.setIn(['previewSize', 'current'], size)
    })
  }

  refsFactory = () => {
    this._refs = {}
    return refName => node => {
      this._refs[refName] = node
    }<commit_msg>fix lint no default case<commit_after>import React, { Component } from 'react'
import { ipcRenderer } from 'electron'
import { connect } from 'react-redux'
import cx from 'classnames'
import pathModule from 'path'
import SplitPane from 'react-split-pane'
import FaFolder from 'react-icons/fa/folder'
import IconClose from 'react-icons/md/close'
import IconEdit from 'react-icons/md/mode-edit'

import { openModal } from 'reducers/modals'

import { readDir, sortFiles, fsRename } from 'helpers/fs'
import { setPreview } from 'actions/preview'
import { updateSettings } from 'actions/settings'

import FileEditor from 'components/FileEditor'
import FilePreview from './FilePreview'
import OldSyntaxDetected from './OldSyntaxDetected'

import './styles.scss'

function renameFile(path, oldName, newName, files) {
  if (oldName === newName) {
    return
  }
  const filesWithoutOld = files.filter(f => f.name !== oldName)
  const fileExists = filesWithoutOld.some(f => f.name === newName)
  if (fileExists) {
    throw new Error('File already exists')
  }
  const oldFullName = pathModule.join(path, oldName)
  const newFullName = pathModule.join(path, newName)
  return fsRename(oldFullName, newFullName)
}

@connect(
  state => ({
    previewSize: state.settings.get('previewSize'),
  }),
  {
    setPreview,
    openModal,
    updateSettings,
  },
  null,
  { withRef: true },
)
class FilesList extends Component {
  state = {
    isAdding: false,
    files: [],
    isDragging: false,
    renamedFile: null,
    newName: '',
    isOldSyntaxDetected: false,
  }

  componentWillMount() {
    this._hasFocused = false
  }

  componentDidMount() {
    this.refresh()
    ipcRenderer.on('browser-window-focus', this.refresh)
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.path !== this.props.path) {
      this.refresh()
    }
    if (!prevState.isAdding && this.state.isAdding) {
      this._inputName.focus()
    }
    if (this.state.files.length > prevState.files.length && this._lastCreated) {
      this._refs[this._lastCreated].focus()
    }
    if (!prevState.renamedFile && this.state.renamedFile) {
      this._renameInput.select()
    }
  }

  componentWillUnmount() {
    this._unmounted = true
    ipcRenderer.removeListener('browser-window-focus', this.refresh)
  }

  handleDetectOldSyntax = () => this.setState({ isOldSyntaxDetected: true })

  handleSubmit = e => {
    e.preventDefault()
    const { path, onAddFile, onActiveFileChange } = this.props
    let name = this._inputName.value
    if (!name) {
      return
    }
    name = `${name}.mjml`
    const fileName = pathModule.join(path, name)
    onAddFile(fileName)
    onActiveFileChange({
      isFolder: false,
      name,
    })
    this._lastCreated = name
    this.toggleAdding()
  }

  handleClickFactory = f => () => {
    const p = pathModule.join(this.props.path, f.name)
    if (f.isFolder) {
      return this.props.onPathChange(p)
    }
    if (this.props.onFileClick) {
      this.props.onFileClick(p)
    }
    // preview will be set by the onChange on editor
    // no need to trigger it here
    if (!p.endsWith('.mjml')) {
      this.props.setPreview(p)
    }
    this.props.onActiveFileChange(f)
  }

  handleClickDirectFactory = (items, i) => () => {
    const sub = items.slice(0, i + 1)
    const relativePath = sub.join(pathModule.sep)
    const path = pathModule.join(this.props.rootPath, relativePath)
    this.props.onPathChange(path)
  }

  handleRemoveFileFactory = f => e => {
    if (e) {
      e.preventDefault()
    }
    const p = pathModule.join(this.props.path, f.name)
    this.props.onRemoveFile(p)
  }

  handleNavigateUp = () => {
    this.props.onPathChange(pathModule.dirname(this.props.path))
  }

  handlePreviewPanelStopDrag = size => {
    this.setCurrentSize(size)
    this.stopDrag()
  }

  handleChangeNewName = e => {
    this.setState({ newName: e.target.value })
  }

  handleCancelRename = () =>
    this.setState({
      renamedFile: null,
      newName: '',
    })

  handleRenameInputKeyDown = async e => {
    switch (
      e.which // eslint-disable-line
    ) {
      case 27:
        this.handleCancelRename()
        break
      case 13:
        try {
          const { path } = this.props
          const { newName, renamedFile, files } = this.state
          await renameFile(path, renamedFile.name, newName, files)
          const newFile = { name: newName, isFolder: false }
          const newFiles = files.map(f => {
            if (f === renamedFile) {
              return newFile
            }
            return f
          })
          sortFiles(newFiles)
          this.setState({ files: newFiles })
          this.props.onActiveFileChange(newFile)
          this.handleCancelRename()
        } catch (e) {} // eslint-disable-line
        break
      default:
        break;
    }
  }

  handleMigrate = () => {
    this._editor.migrateToMJML4()
    this.setState({ isOldSyntaxDetected: false })
  }

  setCurrentSize = size => {
    this.props.updateSettings(settings => {
      return settings.setIn(['previewSize', 'current'], size)
    })
  }

  refsFactory = () => {
    this._refs = {}
    return refName => node => {
      this._refs[refName] = node
    }
{'fraction_non_alphanumeric': 0.12738975886252282, 'fraction_numerical': 0.0013449899125756557, 'mean_word_length': 2.745951781216265, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 51, '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': '502582', 'n_tokens_mistral': 3362, 'n_tokens_neox': 3306, 'n_words': 686}