hunk.code_window:  * @summary FLASH_STATE fields that can't be nil
    * @constant
    * @private
    */
   const flashStateNoNilFields = [
     'percentage',
     'eta',
     'speed',
     'totalSpeed'
   ]
  
hunk.labels: keep keep keep keep keep replace replace keep keep keep keep
hunk.file_path: lib/gui/app/models/store.js
hunk.type: replace
file: /*
   * Copyright 2018 resin.io
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *    http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  'use strict'
  
  /**
   * @module Etcher.Components.SVGIcon
   */
  
  const _ = require('lodash')
  const react = require('react')
  const propTypes = require('prop-types')
  const path = require('path')
  const fs = require('fs')
  const analytics = require('../../modules/analytics')
  const domParser = new window.DOMParser()
  
  const DEFAULT_SIZE = '40px'
  
  /**
   * @summary Try to parse SVG contents and return it data encoded
   *
   * @param {String} contents - SVG XML contents
   * @returns {String|null}
   *
   * @example
   * const encodedSVG = tryParseSVGContents('<svg><path></path></svg>')
   *
   * img.src = encodedSVG
   */
  const tryParseSVGContents = (contents) => {
    const doc = domParser.parseFromString(contents, 'image/svg+xml')
    const parserError = doc.querySelector('parsererror')
    const svg = doc.querySelector('svg')
  
    if (!parserError && svg) {
      return `data:image/svg+xml,${encodeURIComponent(svg.outerHTML)}`
    }
  
    return null
  }
  
  /* eslint-disable jsdoc/require-example */
  
  /**
   * @summary SVG element that takes both filepaths and file contents
   * @type {Object}
   * @public
   */
  class SVGIcon extends react.Component {
    /**
     * @summary Render the SVG
     * @returns {react.Element}
     */
    render () {
      // __dirname behaves strangely inside a Webpack bundle,
      // so we need to provide different base directories
      // depending on whether __dirname is absolute or not,
      // which helps detecting a Webpack bundle.
      // We use global.__dirname inside a Webpack bundle since
      // that's the only way to get the "real" __dirname.
      const baseDirectory = path.isAbsolute(__dirname)
        ? path.join(__dirname, '..')
        // eslint-disable-next-line no-underscore-dangle
        : global.__dirname
  
      let svgData = ''
  
      _.find(this.props.contents, (content) => {
        const attempt = tryParseSVGContents(content)
  
        if (attempt) {
          svgData = attempt
          return true
        }
  
        return false
      })
  
      if (!svgData) {
        _.find(this.props.paths, (relativePath) => {
          // This means the path to the icon should be
          // relative to *this directory*.
          // TODO: There might be a way to compute the path
          // relatively to the `index.html`.
          const imagePath = path.join(baseDirectory, 'assets', relativePath)
  
          const contents = _.attempt(() => {
            return fs.readFileSync(imagePath, {
              encoding: 'utf8'
            })
          })
  
          if (_.isError(contents)) {
            analytics.logException(contents)
            return false
          }
  
          const parsed = _.attempt(tryParseSVGContents, contents)
  
          if (parsed) {
            svgData = parsed
            return true
          }
  
          return false
        })
      }
  
      const width = this.props.width || DEFAULT_SIZE
      const height = this.props.height || DEFAULT_SIZE
  
      return react.createElement('img', {
        className: 'svg-icon',
        style: {
          width,
          height
        },
        src: svgData,
        disabled: this.props.disabled
      })
    }
  
    /**
     * @summary Cause a re-render due to changed element properties
     * @param {Object} nextProps - the new properties
     */
    componentWillReceiveProps (nextProps) {
      // This will update the element if the properties change
      this.setState(nextProps)
    }
  }
  
  SVGIcon.propTypes = {
  
    /**
     * @summary Paths to SVG files to be tried in succession if any fails
     */
    paths: propTypes.array,
  
    /**
     * @summary List of embedded SVG contents to be tried in succession if any fails
     */
    contents: propTypes.array,
  
    /**
     * @summary SVG image width unit
     */
    width: propTypes.string,
  
    /**
     * @summary SVG image height unit
     */
    height: propTypes.string,
  
    /**
     * @summary Should the element visually appear grayed out and disabled?
     */
    disabled: propTypes.bool
  
  }
  
  module.exports = SVGIcon
  