<commit_before>/*jslint node : true, nomen: true, plusplus: true, vars: true, eqeq: true,*/
/*
 * 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";

var async = require('async');
var QueryStream = require('pg-query-stream');

module.exports = function setup(options, imports, register) {
    var pg = require('pg');

    function createPool(config) {
        return {
            'connection': function (callback) {
                pg.connect(config.url, function (err, handle, done) {
                    callback(err, handle);
                    done();
                });
            },
            'query' : function (sql, params, callback) {
                connection(function (err, handle) {
                    handle.query(sql, params, function (err, res) {
                        callback(err, res);
                    });
                });
            },
            'queryStream' : function (sql, params, callback) {
                connection(function (err, handle) {
                    if (err) {
                        return callback(err);
                    }
                    var query = new QueryStream(sql, params);
                    var stream = handle.query(query);
                    stream.once('end', done);
                    callback(null, stream);
                });
            }
        };
    }

    function checkConnection(pool, cb) {
        connection(function (err, handle) {
            if (err) {
                return cb('unable to create pg connection to ' + pool.url + ' : ' + err);
            }
            cb();
        });
    }

    function createPools(opts) {
        var res = { db : {}};
        if (opts.url) {
            res.db = createPool(opts);
        }
        Object.keys(opts).forEach(function (key) {
            if (opts[key] && opts[key].url) {
                var pool = createPool(opts[key]);
                res.db[key] = pool;
                if (opts[key]['default']) {
                    Object.keys(pool).forEach(function (key) {
                        res.db[key] = pool[key];
                    });
                }
            }
        });
        return res;
    }

    var pools = createPools(options);

    if (options.checkOnStartUp) {
        var filtered = Object.keys(pools).filter(function (key) {
            return pools[key].connection;
        }).map(function (el) {
            return pools[el];
        });
        async.each(filtered, checkConnection, function (err) {
            if (err) {
                return register(err);
            }
            register(null, pools);
        });
    } else {
        register(null, pools);
    }
};
<commit_msg>Add finally close when exception are raised, to avoid not closed connection<commit_after>/*jslint node : true, nomen: true, plusplus: true, vars: true, eqeq: true,*/
/*
 * 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";

var async = require('async');
var QueryStream = require('pg-query-stream');

module.exports = function setup(options, imports, register) {
    var pg = require('pg');

    function createPool(config) {
        return {
            'connection': function (callback) {
                pg.connect(config.url, function (err, handle, done) {
                    try {
                        callback(err, handle);
                    } finally {
                        done();
                    }
                });
            },
            'query': function (sql, params, callback) {
                connection(function (err, handle) {
                    handle.query(sql, params, function (err, res) {
                        callback(err, res);
                    });
                });
            },
            'queryStream': function (sql, params, callback) {
                connection(function (err, handle) {
                    if (err) {
                        return callback(err);
                    }
                    var query = new QueryStream(sql, params);
                    var stream = handle.query(query);
                    stream.once('end', done);
                    callback(null, stream);
                });
            }
        };
    }

    function checkConnection(pool, cb) {
        connection(function (err, handle) {
            if (err) {
                return cb('unable to create pg connection to ' + pool.url + ' : ' + err);
            }
            cb();
        });
    }

    function createPools(opts) {
        var res = {db: {}};
        if (opts.url) {
            res.db = createPool(opts);
        }
        Object.keys(opts).forEach(function (key) {
            if (opts[key] && opts[key].url) {
                var pool = createPool(opts[key]);
                res.db[key] = pool;
                if (opts[key]['default']) {
                    Object.keys(pool).forEach(function (key) {
                        res.db[key] = pool[key];
                    });
                }
            }
        });
        return res;
    }

    var pools = createPools(options);

    if (options.checkOnStartUp) {
        var filtered = Object.keys(pools).filter(function (key) {
            return pools[key].connection;
        }).map(function (el) {
            return pools[el];
        });
        async.each(filtered, checkConnection, function (err) {
            if (err) {
                return register(err);
            }
            register(null, pools);
        });
    } else {
        register(null, pools);
    }
};
<|endoftext|>


<commit_before>const React = require('react')
const { Component } = React
const PropTypes = require('prop-types')
const { getDeviceId, getFacingModePattern } = require('./getDeviceId')
const havePropsChanged = require('./havePropsChanged')
const createBlob = require('./createBlob')

// Require adapter to support older browser implementations
require('webrtc-adapter')

// Inline worker.js as a string value of workerBlob.
// eslint-disable-next-line
let workerBlob = createBlob([__inline('../lib/worker.js')], {
  type: 'application/javascript',
})

// Props that are allowed to change dynamicly
const propsKeys = ['delay', 'legacyMode', 'facingMode']

module.exports = class Reader extends Component {
  static propTypes = {
    onScan: PropTypes.func.isRequired,
    onError: PropTypes.func.isRequired,
    onLoad: PropTypes.func,
    onImageLoad: PropTypes.func,
    delay: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
    facingMode: PropTypes.oneOf(['user', 'environment']),
    legacyMode: PropTypes.bool,
    resolution: PropTypes.number,
    showViewFinder: PropTypes.bool,
    style: PropTypes.any,
    className: PropTypes.string,
  };
  static defaultProps = {
    delay: 500,
    resolution: 600,
    facingMode: 'environment',
    showViewFinder: true,
  };

  els = {};

  constructor(props) {
    super(props)

    this.state = {
      mirrorVideo: false,
    }

    // Bind function to the class
    this.initiate = this.initiate.bind(this)
    this.initiateLegacyMode = this.initiateLegacyMode.bind(this)
    this.check = this.check.bind(this)
    this.handleVideo = this.handleVideo.bind(this)
    this.handleLoadStart = this.handleLoadStart.bind(this)
    this.handleInputChange = this.handleInputChange.bind(this)
    this.clearComponent = this.clearComponent.bind(this)
    this.handleReaderLoad = this.handleReaderLoad.bind(this)
    this.openImageDialog = this.openImageDialog.bind(this)
    this.handleWorkerMessage = this.handleWorkerMessage.bind(this)
    this.setRefFactory = this.setRefFactory.bind(this)
  }
  componentDidMount() {
    // Initiate web worker execute handler according to mode.
    this.worker = new Worker(URL.createObjectURL(workerBlob))
    this.worker.onmessage = this.handleWorkerMessage

    if (!this.props.legacyMode) {
      this.initiate()
    } else {
      this.initiateLegacyMode()
    }
  }
  componentWillReceiveProps(nextProps) {
    // React according to change in props
    const changedProps = havePropsChanged(this.props, nextProps, propsKeys)

    for (const prop of changedProps) {
      if (prop == 'facingMode') {
        this.clearComponent()
        this.initiate(nextProps)
        break
      } else if (prop == 'delay') {
        if (this.props.delay == false && !nextProps.legacyMode) {
          this.timeout = setTimeout(this.check, nextProps.delay)
        }
        if (nextProps.delay == false) {
          clearTimeout(this.timeout)
        }
      } else if (prop == 'legacyMode') {
        if (this.props.legacyMode && !nextProps.legacyMode) {
          this.clearComponent()
          this.initiate(nextProps)
        } else {
          this.clearComponent()
          this.componentDidUpdate = this.initiateLegacyMode
        }
        break
      }
    }
  }
  shouldComponentUpdate(nextProps, nextState) {
    if(nextState !== this.state){
      return true
    }

    // Only render when the `propsKeys` have changed.
    const changedProps = havePropsChanged(this.props, nextProps, propsKeys)
    return changedProps.length > 0
  }
  componentWillUnmount() {
    // Stop web-worker and clear the component
    if (this.worker) {
      this.worker.terminate()
      this.worker = undefined
    }
    this.clearComponent()
  }
  clearComponent() {
    // Remove all event listeners and variables
    if (this.timeout) {
      clearTimeout(this.timeout)
      this.timeout = undefined
    }
    if (this.stopCamera) {
      this.stopCamera()
    }
    if (this.reader) {
      this.reader.removeEventListener('load', this.handleReaderLoad)
    }
    if (this.els.img) {
      this.els.img.removeEventListener('load', this.check)
    }
  }
  initiate(props = this.props) {
    const { onError, facingMode } = props

    // Check browser facingMode constraint support
    // Firefox ignores facingMode or deviceId constraints
    const isFirefox = /firefox/i.test(navigator.userAgent)
    const supported = navigator.mediaDevices !== undefined
      ? navigator.mediaDevices.getSupportedConstraints()
      : {}
    const constraints = {}

    if(supported.facingMode) {
      constraints.facingMode = { ideal: facingMode }
    }
    if(supported.aspectRatio) {
      constraints.aspectRatio = 1
    }
    if(supported.frameRate) {
      constraints.frameRate = {ideal: 25, min: 10}
    }
    const vConstraintsPromise = (supported.facingMode || isFirefox)
      ? Promise.resolve(constraints)
      : getDeviceId(facingMode).then(deviceId => ({ deviceId }))

    vConstraintsPromise
      .then(video => navigator.mediaDevices.getUserMedia({ video }))
      .then(this.handleVideo)
      .catch(onError)
  }
  handleVideo(stream) {
    const { preview } = this.els

    // Handle different browser implementations of MediaStreams as src
    if(preview.srcObject !== undefined){
      preview.srcObject = stream
    } else if (preview.mozSrcObject !== undefined) {
      preview.mozSrcObject = stream
    } else if (window.URL.createObjectURL) {
      preview.src = window.URL.createObjectURL(stream)
    } else if (window.webkitURL) {
      preview.src = window.webkitURL.createObjectURL(stream)
    } else {
      preview.src = stream
    }

    // IOS play in fullscreen
    preview.playsInline = true

    const streamTrack = stream.getTracks()[0]
    // Assign `stopCamera` so the track can be stopped once component is cleared
    this.stopCamera = streamTrack.stop.bind(streamTrack)

    preview.addEventListener('loadstart', this.handleLoadStart)

    const facingUserPattern = getFacingModePattern('user')
    const isUserFacing = facingUserPattern.test(streamTrack.label)
    this.setState({ mirrorVideo: isUserFacing })
  }
  handleLoadStart() {
    const { delay, onLoad } = this.props
    const preview = this.els.preview
    preview.play()

    if(typeof onLoad == 'function') {
      onLoad()
    }

    if (typeof delay == 'number') {
      this.timeout = setTimeout(this.check, delay)
    }

    // Some browsers call loadstart continuously
    preview.removeEventListener('loadstart', this.handleLoadStart)
  }
  check() {
    const { legacyMode, resolution, delay } = this.props
    const { preview, canvas, img } = this.els

    // Get image/video dimensions
    let width = Math.floor(legacyMode ? img.naturalWidth : preview.videoWidth)
    let height = Math.floor(legacyMode ? img.naturalHeight : preview.videoHeight)

    // Canvas draw offsets
    let hozOffset = 0
    let vertOffset = 0

    // Scale image to correct resolution
    if(legacyMode){
      // Keep image aspect ratio
      const greatestSize = width > height ? width : height
      const ratio = resolution / greatestSize

      height = ratio * height
      width = ratio * width

      canvas.width = width
      canvas.height = height
    }else{
      // Crop image to fit 1:1 aspect ratio
      const smallestSize = width < height ? width : height
      const ratio = resolution / smallestSize

      height = ratio * height
      width = ratio * width

      vertOffset = (height - resolution) / 2 * -1
      hozOffset = (width - resolution) / 2 * -1

      canvas.width = resolution
      canvas.height = resolution
    }

    const previewIsPlaying = preview &&
      preview.readyState === preview.HAVE_ENOUGH_DATA

    if (legacyMode || previewIsPlaying) {
      const ctx = canvas.getContext('2d')

      ctx.drawImage(legacyMode ? img : preview, hozOffset, vertOffset, width, height)

      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
      // Send data to web-worker
      this.worker.postMessage(imageData)
    } else {
      // Preview not ready -> check later
      this.timeout = setTimeout(this.check, delay)
    }
  }
  handleWorkerMessage(e) {
    const { onScan, legacyMode, delay } = this.props
    const decoded = e.data
    onScan(decoded || null)

    if (!legacyMode && typeof delay == 'number' && this.worker) {
      this.timeout = setTimeout(this.check, delay)
    }
  }
  initiateLegacyMode() {
    this.reader = new FileReader()
    this.reader.addEventListener('load', this.handleReaderLoad)
    this.els.img.addEventListener('load', this.check, false)

    // Reset componentDidUpdate
    this.componentDidUpdate = undefined

    if(typeof this.props.onLoad == 'function') {
      this.props.onLoad()
    }
  }
  handleInputChange(e) {
    const selectedImg = e.target.files[0]
    this.reader.readAsDataURL(selectedImg)
  }
  handleReaderLoad(e) {
    // Set selected image blob as img source
    this.els.img.src = e.target.result
  }
  openImageDialog() {
    // Function to be executed by parent in user action context to trigger img file uploader
    this.els.input.click()
  }
  setRefFactory(key) {
    return element => {
      this.els[key] = element
    }
  }
  render() {
    const {
      style,
      className,
      onImageLoad,
      legacyMode,
      showViewFinder,
      facingMode
    } = this.props

    const containerStyle = {
      position: 'relative',
      width: '100%',
      paddingTop: '100%',
    }
    const hiddenStyle = { display: 'none' }
    const previewStyle = {
      top: 0,
      left: 0,
      display: 'block',
      position: 'absolute',
      overflow: 'hidden',
      width: '100%',
      height: '100%',
    }
    const videoPreviewStyle = {
      ...previewStyle,
      objectFit: 'cover',
      transform: this.state.mirrorVideo ? 'scaleX(-1)' : undefined,
    }
    const imgPreviewStyle = {
      ...previewStyle,
      objectFit: 'scale-down',
    }

    const viewFinderStyle = {
      top: 0,
      left: 0,
      zIndex: 1,
      boxSizing: 'border-box',
      border: '50px solid rgba(0, 0, 0, 0.3)',
      boxShadow: 'inset 0 0 0 5px rgba(255, 0, 0, 0.5)',
      position: 'absolute',
      width: '100%',
      height: '100%',
    }

    return (

          {
            (!legacyMode && showViewFinder)
            ?

            : null
          }
          {
            legacyMode
              ? <input
                style={hiddenStyle}
                type="file"
                accept="image/*"
                ref={this.setRefFactory('input')}
                onChange={this.handleInputChange}
              />
              : null
          }
          {
            legacyMode
              ?
              : <video style={videoPreviewStyle} ref={this.setRefFactory('preview')} />
          }

          <canvas style={hiddenStyle} ref={this.setRefFactory('canvas')} />

    )
  }
}
<commit_msg>fix #71<commit_after>const React = require('react')
const { Component } = React
const PropTypes = require('prop-types')
const { getDeviceId, getFacingModePattern } = require('./getDeviceId')
const havePropsChanged = require('./havePropsChanged')
const createBlob = require('./createBlob')

// Require adapter to support older browser implementations
require('webrtc-adapter')

// Inline worker.js as a string value of workerBlob.
// eslint-disable-next-line
let workerBlob = createBlob([__inline('../lib/worker.js')], {
  type: 'application/javascript',
})

// Props that are allowed to change dynamicly
const propsKeys = ['delay', 'legacyMode', 'facingMode']

module.exports = class Reader extends Component {
  static propTypes = {
    onScan: PropTypes.func.isRequired,
    onError: PropTypes.func.isRequired,
    onLoad: PropTypes.func,
    onImageLoad: PropTypes.func,
    delay: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
    facingMode: PropTypes.oneOf(['user', 'environment']),
    legacyMode: PropTypes.bool,
    resolution: PropTypes.number,
    showViewFinder: PropTypes.bool,
    style: PropTypes.any,
    className: PropTypes.string,
  };
  static defaultProps = {
    delay: 500,
    resolution: 600,
    facingMode: 'environment',
    showViewFinder: true,
  };

  els = {};

  constructor(props) {
    super(props)

    this.state = {
      mirrorVideo: false,
    }

    // Bind function to the class
    this.initiate = this.initiate.bind(this)
    this.initiateLegacyMode = this.initiateLegacyMode.bind(this)
    this.check = this.check.bind(this)
    this.handleVideo = this.handleVideo.bind(this)
    this.handleLoadStart = this.handleLoadStart.bind(this)
    this.handleInputChange = this.handleInputChange.bind(this)
    this.clearComponent = this.clearComponent.bind(this)
    this.handleReaderLoad = this.handleReaderLoad.bind(this)
    this.openImageDialog = this.openImageDialog.bind(this)
    this.handleWorkerMessage = this.handleWorkerMessage.bind(this)
    this.setRefFactory = this.setRefFactory.bind(this)
  }
  componentDidMount() {
    // Initiate web worker execute handler according to mode.
    this.worker = new Worker(URL.createObjectURL(workerBlob))
    this.worker.onmessage = this.handleWorkerMessage

    if (!this.props.legacyMode) {
      this.initiate()
    } else {
      this.initiateLegacyMode()
    }
  }
  componentWillReceiveProps(nextProps) {
    // React according to change in props
    const changedProps = havePropsChanged(this.props, nextProps, propsKeys)

    for (const prop of changedProps) {
      if (prop == 'facingMode') {
        this.clearComponent()
        this.initiate(nextProps)
        break
      } else if (prop == 'delay') {
        if (this.props.delay == false && !nextProps.legacyMode) {
          this.timeout = setTimeout(this.check, nextProps.delay)
        }
        if (nextProps.delay == false) {
          clearTimeout(this.timeout)
        }
      } else if (prop == 'legacyMode') {
        if (this.props.legacyMode && !nextProps.legacyMode) {
          this.clearComponent()
          this.initiate(nextProps)
        } else {
          this.clearComponent()
          this.componentDidUpdate = this.initiateLegacyMode
        }
        break
      }
    }
  }
  shouldComponentUpdate(nextProps, nextState) {
    if(nextState !== this.state){
      return true
    }

    // Only render when the `propsKeys` have changed.
    const changedProps = havePropsChanged(this.props, nextProps, propsKeys)
    return changedProps.length > 0
  }
  componentWillUnmount() {
    // Stop web-worker and clear the component
    if (this.worker) {
      this.worker.terminate()
      this.worker = undefined
    }
    this.clearComponent()
  }
  clearComponent() {
    // Remove all event listeners and variables
    if (this.timeout) {
      clearTimeout(this.timeout)
      this.timeout = undefined
    }
    if (this.stopCamera) {
      this.stopCamera()
    }
    if (this.reader) {
      this.reader.removeEventListener('load', this.handleReaderLoad)
    }
    if (this.els.img) {
      this.els.img.removeEventListener('load', this.check)
    }
  }
  initiate(props = this.props) {
    const { onError, facingMode } = props

    // Check browser facingMode constraint support
    // Firefox ignores facingMode or deviceId constraints
    const isFirefox = /firefox/i.test(navigator.userAgent)
    const supported = navigator.mediaDevices !== undefined
      ? navigator.mediaDevices.getSupportedConstraints()
      : {}
    const constraints = {}

    if(supported.facingMode) {
      constraints.facingMode = { ideal: facingMode }
    }
    if(supported.aspectRatio) {
      constraints.aspectRatio = 1
    }
    if(supported.frameRate) {
      constraints.frameRate = {ideal: 25, min: 10}
    }
    const vConstraintsPromise = (supported.facingMode || isFirefox)
      ? Promise.resolve(constraints)
      : getDeviceId(facingMode).then(deviceId => ({ deviceId }))

    vConstraintsPromise
      .then(video => navigator.mediaDevices.getUserMedia({ video }))
      .then(this.handleVideo)
      .catch(onError)
  }
  handleVideo(stream) {
    const { preview } = this.els

    // Preview element hasn't been rendered so wait for it.
    if (!preview) {
      setTimeout(this.handleVideo, 200, stream)
    }

    // Handle different browser implementations of MediaStreams as src
    if(preview.srcObject !== undefined){
      preview.srcObject = stream
    } else if (preview.mozSrcObject !== undefined) {
      preview.mozSrcObject = stream
    } else if (window.URL.createObjectURL) {
      preview.src = window.URL.createObjectURL(stream)
    } else if (window.webkitURL) {
      preview.src = window.webkitURL.createObjectURL(stream)
    } else {
      preview.src = stream
    }

    // IOS play in fullscreen
    preview.playsInline = true

    const streamTrack = stream.getTracks()[0]
    // Assign `stopCamera` so the track can be stopped once component is cleared
    this.stopCamera = streamTrack.stop.bind(streamTrack)

    preview.addEventListener('loadstart', this.handleLoadStart)

    const facingUserPattern = getFacingModePattern('user')
    const isUserFacing = facingUserPattern.test(streamTrack.label)
    this.setState({ mirrorVideo: isUserFacing })
  }
  handleLoadStart() {
    const { delay, onLoad } = this.props
    const preview = this.els.preview
    preview.play()

    if(typeof onLoad == 'function') {
      onLoad()
    }

    if (typeof delay == 'number') {
      this.timeout = setTimeout(this.check, delay)
    }

    // Some browsers call loadstart continuously
    preview.removeEventListener('loadstart', this.handleLoadStart)
  }
  check() {
    const { legacyMode, resolution, delay } = this.props
    const { preview, canvas, img } = this.els

    // Get image/video dimensions
    let width = Math.floor(legacyMode ? img.naturalWidth : preview.videoWidth)
    let height = Math.floor(legacyMode ? img.naturalHeight : preview.videoHeight)

    // Canvas draw offsets
    let hozOffset = 0
    let vertOffset = 0

    // Scale image to correct resolution
    if(legacyMode){
      // Keep image aspect ratio
      const greatestSize = width > height ? width : height
      const ratio = resolution / greatestSize

      height = ratio * height
      width = ratio * width

      canvas.width = width
      canvas.height = height
    }else{
      // Crop image to fit 1:1 aspect ratio
      const smallestSize = width < height ? width : height
      const ratio = resolution / smallestSize

      height = ratio * height
      width = ratio * width

      vertOffset = (height - resolution) / 2 * -1
      hozOffset = (width - resolution) / 2 * -1

      canvas.width = resolution
      canvas.height = resolution
    }

    const previewIsPlaying = preview &&
      preview.readyState === preview.HAVE_ENOUGH_DATA

    if (legacyMode || previewIsPlaying) {
      const ctx = canvas.getContext('2d')

      ctx.drawImage(legacyMode ? img : preview, hozOffset, vertOffset, width, height)

      const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)
      // Send data to web-worker
      this.worker.postMessage(imageData)
    } else {
      // Preview not ready -> check later
      this.timeout = setTimeout(this.check, delay)
    }
  }
  handleWorkerMessage(e) {
    const { onScan, legacyMode, delay } = this.props
    const decoded = e.data
    onScan(decoded || null)

    if (!legacyMode && typeof delay == 'number' && this.worker) {
      this.timeout = setTimeout(this.check, delay)
    }
  }
  initiateLegacyMode() {
    this.reader = new FileReader()
    this.reader.addEventListener('load', this.handleReaderLoad)
    this.els.img.addEventListener('load', this.check, false)

    // Reset componentDidUpdate
    this.componentDidUpdate = undefined

    if(typeof this.props.onLoad == 'function') {
      this.props.onLoad()
    }
  }
  handleInputChange(e) {
    const selectedImg = e.target.files[0]
    this.reader.readAsDataURL(selectedImg)
  }
  handleReaderLoad(e) {
    // Set selected image blob as img source
    this.els.img.src = e.target.result
  }
  openImageDialog() {
    // Function to be executed by parent in user action context to trigger img file uploader
    this.els.input.click()
  }
  setRefFactory(key) {
    return element => {
      this.els[key] = element
    }
  }
  render() {
    const {
      style,
      className,
      onImageLoad,
      legacyMode,
      showViewFinder,
      facingMode
    } = this.props

    const containerStyle = {
      position: 'relative',
      width: '100%',
      paddingTop: '100%',
    }
    const hiddenStyle = { display: 'none' }
    const previewStyle = {
      top: 0,
      left: 0,
      display: 'block',
      position: 'absolute',
      overflow: 'hidden',
      width: '100%',
      height: '100%',
    }
    const videoPreviewStyle = {
      ...previewStyle,
      objectFit: 'cover',
      transform: this.state.mirrorVideo ? 'scaleX(-1)' : undefined,
    }
    const imgPreviewStyle = {
      ...previewStyle,
      objectFit: 'scale-down',
    }

    const viewFinderStyle = {
      top: 0,
      left: 0,
      zIndex: 1,
      boxSizing: 'border-box',
      border: '50px solid rgba(0, 0, 0, 0.3)',
      boxShadow: 'inset 0 0 0 5px rgba(255, 0, 0, 0.5)',
      position: 'absolute',
      width: '100%',
      height: '100%',
    }

    return (

          {
            (!legacyMode && showViewFinder)
            ?

            : null
          }
          {
            legacyMode
              ? <input
                style={hiddenStyle}
                type="file"
                accept="image/*"
                ref={this.setRefFactory('input')}
                onChange={this.handleInputChange}
              />
              : null
          }
          {
            legacyMode
              ?
              : <video style={videoPreviewStyle} ref={this.setRefFactory('preview')} />
          }

          <canvas style={hiddenStyle} ref={this.setRefFactory('canvas')} />

    )
  }
}
<|endoftext|>


<commit_before>/**
 * UI
 * control buttons, modals, share input and title
 */
var Ui = ( function() {

	var settings = {
		selector: {
			title:  'h1',
			button: '.control-button',
			controls: {
				toggle: '.ui-toggle--controls',
			},
			share: {
				toggle: '.ui-toggle--share',
				input:  '.share-url-input',
				button: '.share-url-button',
				close:  '.ui-modal-close--share',
				link: 	'.share-link'
			},
			info: {
				toggle: '.ui-toggle--info',
				close:  '.ui-modal-close--info'
			},
			modal: {
				wrapper: '[data-modal]',
				toggle:  '[data-modal-action="toggle"]'
			}
		},
		isVisible: {
			controls: 	false,
			share: 		false,
			info: 		false
		},
		shareServices: {
			facebook: {
				label: 	'Facebook',
				url: 	'https://facebook.com/sharer/sharer.php?u={url}'
			},
			twitter: {
				label: 	'Twitter',
				url: 	'http://www.twitter.com/share?url={url}'
			}
		}
	}

	var init = function() {
		// enable controls on touch devices
		if( Modernizr.touchevents ) {
			toggleControls();
		}

		// show info UI on first visit
		if( !Cookies.get( '108--visited' ) ) {
			toggleModal( 'info' );
		}
		Cookies.set( '108--visited', true, { expires: 30, path: '' } );

		bindEventHandlers();
	}

	var bindEventHandlers = function() {
		$( document )
			// toggle controls
			.on( 'click', settings.selector.controls.toggle, function( event ) {
				event.preventDefault();

				toggleControls();
			} )
			// toggle modal
			.on( 'click', settings.selector.modal.toggle, function( event ) {
				event.preventDefault();

				var id = $( this ).closest( settings.selector.modal.wrapper ).attr( 'data-modal' );
				toggleModal( id );
			} )
			// control buttons
			.on( 'click', settings.selector.button, function( event ) {
				event.preventDefault();
			} )
			.on( 'mousedown touchstart', settings.selector.button, function( event ) {
				event.preventDefault();

				Debug.log( 'mousedown / touchstart' );

				var button = $( this );

				// sample buttons
				if( button.attr( 'data-sample' ) ) {
					var sample = parseInt( $( this ).attr( 'data-sample' ) );

					$( document ).trigger( 'ui/clickButton', [{
						sample: sample
					}] );
				}

				// action buttons
				if( button.attr( 'data-action' ) ) {
					var action = $( this ).attr( 'data-action' );

					$( document ).trigger( 'ui/clickButton', [{
						action: action
					}] );
				}
			} )
			// share links
			.on( 'click', settings.selector.share.link, function( event ) {
				event.preventDefault();

				var service = $( this ).attr( 'data-service' );
				if( service ) {
					openShareWindow( service, settings.url );
				}
			} )
			.on( 'sequencer/playSample', function( event, data ) {
				var sample = data.sample;
				highlightButton( sample );
				highlightTitle();
			} )
			.on( 'sequencer/saveSequence', function( event, data ) {
				setUrl( data.data );
			} )
			.on( 'focus', settings.selector.share.input, function( event ) {
				$( this ).select();
			} );

			new Clipboard( settings.selector.share.button );
	}

	var highlightButton = function( sample ) {
		Debug.log( 'Ui.highlightButton()', sample );

		var button = $( settings.selector.button ).filter( '[data-sample="' +  sample + '"]' );
		var color = $( 'html' ).css( 'backgroundColor' );

		new TimelineLite()
			.to(
				button,
				0.05,
				{
					backgroundColor: '#fff'
				}
			)
			.to(
				button,
				0.05,
				{
					backgroundColor: 'rgba( 255,255,255,0.01 )'
				}
			);
	}

	var highlightTitle = function() {
		Debug.log( 'Ui.highlightTitle()' );

		if( !Modernizr.touchevents && Viewport.getWidth() > 768 ) {
			var title = $( settings.selector.title );

			new TimelineLite()
				.to(
					title,
					0.01,
					{
						opacity: 1
					}
				)
				.to(
					title,
					0.05,
					{
						opacity: 0.5
					}
				);
		}
	}

	var toggleControls = function() {
		Debug.log( 'Ui.toggleControls()' );

		if( !settings.isVisible.controls ) {
			$( 'html' )
				.addClass( 'visible--ui-controls' );
		} else {
			$( 'html' )
				.removeClass( 'visible--ui-controls' );
		}

		settings.isVisible.controls = !settings.isVisible.controls;
	}

	var toggleModal = function( id ) {
		Debug.log( 'Ui.toggleModal()', id );

		if( !settings.isVisible[id] ) {
			$( 'html' )
				.addClass( 'visible--ui-' + id );
		} else {
			$( 'html' )
				.removeClass( 'visible--ui-' + id );
		}

		settings.isVisible[id] = !settings.isVisible[id];
	}

	var setUrl = function( hash ) {
		Debug.log( 'Ui.setUrl()', hash );

		var url = location.protocol + '//' + location.hostname + location.pathname;
		settings.url = url + '#' + hash;

		$( settings.selector.share.input ).val( settings.url );
	}

	var openShareWindow = function( service, url ) {
		if( settings.shareServices[service] ) {
			var url = settings.shareServices[service].url.replace( '{url}', url );
			window.open( url, '108Share', 'width=520,height=320,menubar=no,location=yes,resizable=no,scrollbars=yes,status=no' );
		}
	}

	return {
		init: function() { init(); }
	}

} )();

$( document ).ready( function() {
	Ui.init();
} );<commit_msg>added demo mode<commit_after>/**
 * UI
 * control buttons, modals, share input and title
 */
var Ui = ( function() {

	var settings = {
		selector: {
			title:  'h1',
			button: '.control-button',
			controls: {
				toggle: '.ui-toggle--controls',
			},
			share: {
				toggle: '.ui-toggle--share',
				input:  '.share-url-input',
				button: '.share-url-button',
				close:  '.ui-modal-close--share',
				link: 	'.share-link'
			},
			info: {
				toggle: '.ui-toggle--info',
				close:  '.ui-modal-close--info'
			},
			modal: {
				wrapper: '[data-modal]',
				toggle:  '[data-modal-action="toggle"]'
			}
		},
		isVisible: {
			controls: 	false,
			share: 		false,
			info: 		false
		},
		shareServices: {
			facebook: {
				label: 	'Facebook',
				url: 	'https://facebook.com/sharer/sharer.php?u={url}'
			},
			twitter: {
				label: 	'Twitter',
				url: 	'http://www.twitter.com/share?url={url}'
			}
		}
	}

	var init = function() {
		// enable controls on touch devices
		if( Modernizr.touchevents ) {
			toggleControls();
		}

		if( location.href.indexOf( 'demo' ) > -1 && !settings.isVisible.controls ) {
			toggleControls();
		}

		// show info UI on first visit
		if( !Cookies.get( '108--visited' ) && location.href.indexOf( 'demo' ) < 0 ) {
			toggleModal( 'info' );
		}
		Cookies.set( '108--visited', true, { expires: 30, path: '' } );

		bindEventHandlers();
	}

	var bindEventHandlers = function() {
		$( document )
			// toggle controls
			.on( 'click', settings.selector.controls.toggle, function( event ) {
				event.preventDefault();

				toggleControls();
			} )
			// toggle modal
			.on( 'click', settings.selector.modal.toggle, function( event ) {
				event.preventDefault();

				var id = $( this ).closest( settings.selector.modal.wrapper ).attr( 'data-modal' );
				toggleModal( id );
			} )
			// control buttons
			.on( 'click', settings.selector.button, function( event ) {
				event.preventDefault();
			} )
			.on( 'mousedown touchstart', settings.selector.button, function( event ) {
				event.preventDefault();

				Debug.log( 'mousedown / touchstart' );

				var button = $( this );

				// sample buttons
				if( button.attr( 'data-sample' ) ) {
					var sample = parseInt( $( this ).attr( 'data-sample' ) );

					$( document ).trigger( 'ui/clickButton', [{
						sample: sample
					}] );
				}

				// action buttons
				if( button.attr( 'data-action' ) ) {
					var action = $( this ).attr( 'data-action' );

					$( document ).trigger( 'ui/clickButton', [{
						action: action
					}] );
				}
			} )
			// share links
			.on( 'click', settings.selector.share.link, function( event ) {
				event.preventDefault();

				var service = $( this ).attr( 'data-service' );
				if( service ) {
					openShareWindow( service, settings.url );
				}
			} )
			.on( 'sequencer/playSample', function( event, data ) {
				var sample = data.sample;
				highlightButton( sample );
				highlightTitle();
			} )
			.on( 'sequencer/saveSequence', function( event, data ) {
				setUrl( data.data );
			} )
			.on( 'focus', settings.selector.share.input, function( event ) {
				$( this ).select();
			} );

			new Clipboard( settings.selector.share.button );
	}

	var highlightButton = function( sample ) {
		Debug.log( 'Ui.highlightButton()', sample );

		var button = $( settings.selector.button ).filter( '[data-sample="' +  sample + '"]' );
		var color = $( 'html' ).css( 'backgroundColor' );

		new TimelineLite()
			.to(
				button,
				0.05,
				{
					backgroundColor: '#fff'
				}
			)
			.to(
				button,
				0.05,
				{
					backgroundColor: 'rgba( 255,255,255,0.01 )'
				}
			);
	}

	var highlightTitle = function() {
		Debug.log( 'Ui.highlightTitle()' );

		if( !Modernizr.touchevents && Viewport.getWidth() > 768 ) {
			var title = $( settings.selector.title );

			new TimelineLite()
				.to(
					title,
					0.01,
					{
						opacity: 1
					}
				)
				.to(
					title,
					0.05,
					{
						opacity: 0.5
					}
				);
		}
	}

	var toggleControls = function() {
		Debug.log( 'Ui.toggleControls()' );

		if( !settings.isVisible.controls ) {
			$( 'html' )
				.addClass( 'visible--ui-controls' );
		} else {
			$( 'html' )
				.removeClass( 'visible--ui-controls' );
		}

		settings.isVisible.controls = !settings.isVisible.controls;
	}

	var toggleModal = function( id ) {
		Debug.log( 'Ui.toggleModal()', id );

		if( !settings.isVisible[id] ) {
			$( 'html' )
				.addClass( 'visible--ui-' + id );
		} else {
			$( 'html' )
				.removeClass( 'visible--ui-' + id );
		}

		settings.isVisible[id] = !settings.isVisible[id];
	}

	var setUrl = function( hash ) {
		Debug.log( 'Ui.setUrl()', hash );

		var url = location.protocol + '//' + location.hostname + location.pathname;
		settings.url = url + '#' + hash;

		$( settings.selector.share.input ).val( settings.url );
	}

	var openShareWindow = function( service, url ) {
		if( settings.shareServices[service] ) {
			var url = settings.shareServices[service].url.replace( '{url}', url );
			window.open( url, '108Share', 'width=520,height=320,menubar=no,location=yes,resizable=no,scrollbars=yes,status=no' );
		}
	}

	return {
		init: function() { init(); }
	}

} )();

$( document ).ready( function() {
	Ui.init();
} );<|endoftext|>


<commit_before>/**
 * alphabetizes css declarations
 * @author: Mark McCann <www.markmccann.me>
 * @license: MIT
 */

var cssAlphabetize = (function(){

    /**
     * extends object
     */
    var extend = function () {
        var a = arguments;
        for( var i = 1; i < a.length; i++ )
            for( var key in a[i] )
                if(a[i].hasOwnProperty(key))
                    a[0][key] = a[i][key];
        return a[0];
    }

    /**
     * splits a declaration into separate parts and
     * determines if is any special case
     */
    var Declaration = function(line) {
        this.line = line.trim();
        this.property = this.line.replace( /^[_\*]?(?:-\w*-(?:(?:osx)-)?)?([^:]*):.*/, '$1' );
        this.original = this.line.replace( /^[_\*]?((?:-\w*-(?:(?:osx)-)?)?[^:]*):.*/, '$1' );
        this.value = this.line.replace( /[^:]*: *([^;'"(]*(\(["']?[^'")]*['"]?\)|["'][^'"]*['"])?[^;'"(]*);.*/, '$1' );
        this.comment = /^\/\*((?!\*\/)(.|\n))*\*\/$/.test(this.line);
        this.hacked = /^[_\*]|(\\9|\\0)+;/.test(this.line);
        this.vendor = /^-\w*-/.test(this.line);
        return this;
    }

    /**
     * default settings for alphabetizer
     */
    var defaults = {
        delimeter: '```',
        ascending: true
    }

    /**
     * return the alphabetize function
     */
    return function( styles, options ) {
        // set alphabetizer settings
        var settings = extend( defaults, options || {} );
        var direction = settings.ascending ? 1 : -1;
        // the contents of each set of brackets that does
        // not contain a set of brackets
        return styles.replace(/{([^{}]*)}/g, function( match, contents ) {
            return '{' + contents
                // make sure there is a final semicolon
                .replace(/([)'"%\w\d])((?:\s*\/\*((?!\*\/)(.|\n))*\*\/)*\s*)$/, '$1;$2')
                // add a unique delimeter after every declaration and comment
                .replace(/([\w\s-]*:([^;'"(])*(\(["']?[^'")]*['"]?\)|["'][^'"]*['"])?([^;])*;( *\/\*((?!\*\/)(.|\n))*\*\/)*|\s*\/\*((?!\*\/)(.|\n))*\*\/)/g, '$1'+settings.delimeter )
                // remove final delimeter to avoid creating empty element in array
                .replace(new RegExp(settings.delimeter+'\\s*$'), '')
                // split string into array by the unique delimeter
                .split(settings.delimeter)
                // sort the array alphabetically
                .sort(function( a, b ){
                    // initialize declartions to compare values
                    a = new Declaration(a); b = new Declaration(b);
                    // comment -vs- comment
                    if( a.comment && b.comment ) return 0;
                    // comment -vs- non-comment
                    if((!a.comment && b.comment)
                    || (a.comment && !b.comment)) return 1;
                    // if the properties match
                    if( a.property == b.property ) {
                        // standard -vs- hack (width:100% -> _width:100%)
                        if(!a.hacked && b.hacked) return -1;
                        if(!b.hacked && a.hacked) return 1;
                        // standard -vs- vendor (border-radius -> -webkit-border-radius)
                        if(!a.vendor && b.vendor) return 1;
                        if(!b.vendor && a.vendor) return -1;
                        // standard -vs- identical (background -> background)
                        if(a.value > b.value) return 1 * direction;
                        if(b.value > a.value) return -1 * direction;
                        // vendor -vs- vendor (-webkit-border-radius -> -webkit-border-radius)
                        if(a.original > b.original) return 1 * direction;
                        if(b.original > a.original) return -1 * direction;
                    }
                    // standard -vs- standard
                    if( a.property < b.property ) return -1 * direction;
                    if( a.property > b.property ) return 1 * direction;
                    // they are equivalent
                    return 0;
                })
                // rejoin the array back into a string
                .join('')
                // add ending space if content present
                + ( /\w|\//.test(contents) ? /(\s*)$/.exec(contents)[0] : '' )
                // add the closing bracket back
                + '}';
        });

    }

})();<commit_msg>fixed bug with curly braces in string.<commit_after>/**
 * alphabetizes css declarations
 * @author: Mark McCann <www.markmccann.me>
 * @license: MIT
 */

var cssAlphabetize = (function(){

    /**
     * extends object
     */
    var extend = function () {
        var a = arguments;
        for( var i = 1; i < a.length; i++ )
            for( var key in a[i] )
                if(a[i].hasOwnProperty(key))
                    a[0][key] = a[i][key];
        return a[0];
    }

    /**
     * splits a declaration into separate parts and
     * determines if is any special case
     */
    var Declaration = function(line) {
        this.line = line.trim();
        this.property = this.line.replace( /^[_\*]?(?:-\w*-(?:(?:osx)-)?)?([^:]*):.*/, '$1' );
        this.original = this.line.replace( /^[_\*]?((?:-\w*-(?:(?:osx)-)?)?[^:]*):.*/, '$1' );
        this.value = this.line.replace( /[^:]*: *([^;'"(]*(\(["']?[^'")]*['"]?\)|["'][^'"]*['"])?[^;'"(]*);.*/, '$1' );
        this.comment = /^\/\*((?!\*\/)(.|\n))*\*\/$/.test(this.line);
        this.hacked = /^[_\*]|(\\9|\\0)+;/.test(this.line);
        this.vendor = /^-\w*-/.test(this.line);
        return this;
    }

    /**
     * default settings for alphabetizer
     */
    var defaults = {
        delimeter: '```',
        ascending: true
    }

    /**
     * return the alphabetize function
     */
    return function( styles, options ) {
        // set alphabetizer settings
        var settings = extend( defaults, options || {} );
        var direction = settings.ascending ? 1 : -1;
        // the contents of each set of brackets that does
        // not contain a set of brackets
        return styles.replace(/{([^{}]*(["'][^\"']*['"])[^{}]*)}/g, function( match, contents ) {
            console.log(
                contents
                // make sure there is a final semicolon
                .replace(/([)'"%\w\d])((?:\s*\/\*((?!\*\/)(.|\n))*\*\/)*\s*)$/, '$1;$2')
                // add a unique delimeter after every declaration and comment
                .replace(/([\w\s-]*:([^;'"(])*(\(["']?[^'")]*['"]?\)|["'][^'"]*['"])*([^;])*;( *\/\*((?!\*\/)(.|\n))*\*\/)*|\s*\/\*((?!\*\/)(.|\n))*\*\/)/g, '$1'+settings.delimeter )
            );
            return '{' + contents
                // make sure there is a final semicolon
                .replace(/([)'"%\w\d])((?:\s*\/\*((?!\*\/)(.|\n))*\*\/)*\s*)$/, '$1;$2')
                // add a unique delimeter after every declaration and comment
                .replace(/([\w\s-]*:([^;'"(])*(\(["']?[^'")]*['"]?\)|["'][^'"]*['"])*([^;])*;( *\/\*((?!\*\/)(.|\n))*\*\/)*|\s*\/\*((?!\*\/)(.|\n))*\*\/)/g, '$1'+settings.delimeter )
                // remove final delimeter to avoid creating empty element in array
                .replace(new RegExp(settings.delimeter+'\\s*$'), '')
                // split string into array by the unique delimeter
                .split(settings.delimeter)
                // sort the array alphabetically
                .sort(function( a, b ){
                    // initialize declartions to compare values
                    a = new Declaration(a); b = new Declaration(b);
                    // comment -vs- comment
                    if( a.comment && b.comment ) return 0;
                    // comment -vs- non-comment
                    if((!a.comment && b.comment)
                    || (a.comment && !b.comment)) return 1;
                    // if the properties match
                    if( a.property == b.property ) {
                        // standard -vs- hack (width:100% -> _width:100%)
                        if(!a.hacked && b.hacked) return -1;
                        if(!b.hacked && a.hacked) return 1;
                        // standard -vs- vendor (border-radius -> -webkit-border-radius)
                        if(!a.vendor && b.vendor) return 1;
                        if(!b.vendor && a.vendor) return -1;
                        // standard -vs- identical (background -> background)
                        if(a.value > b.value) return 1 * direction;
                        if(b.value > a.value) return -1 * direction;
                        // vendor -vs- vendor (-webkit-border-radius -> -webkit-border-radius)
                        if(a.original > b.original) return 1 * direction;
                        if(b.original > a.original) return -1 * direction;
                    }
                    // standard -vs- standard
                    if( a.property < b.property ) return -1 * direction;
                    if( a.property > b.property ) return 1 * direction;
                    // they are equivalent
                    return 0;
                })
                // rejoin the array back into a string
                .join('')
                // add ending space if content present
                + ( /\w|\//.test(contents) ? /(\s*)$/.exec(contents)[0] : '' )
                // add the closing bracket back
                + '}';
        });

    }

})();<|endoftext|>


<commit_before>// Requires
var gui = require('nw.gui');

var Q = require('q');
var _ = require('lodash');

var fs = require('fs');
var path = require('path');
var querystring = require("querystring");

var CodeboxIO = require('codebox-io').Client;

// Local storage utilities
var storage = {
    get: function(key, def) {
        try {
            return JSON.parse(window.localStorage[key]);
        } catch(err) {
            return window.localStorage[key] || def;
        }
    },
        set: function(key, value) {
        window.localStorage[key] = JSON.stringify(value);
    }
};

// Config
var codeboxIoHost = "https://www.codebox.io";

// Port allocation
var qClass = require('qpatch').qClass;
var harbor = qClass(require('harbor'));
var ports = new harbor(19000, 20000);

// DOM elements
var $directorySelector = $('#directory-selector');
var $projectList = $('#projects');
var $alert = $("#body .alert");
var $btnOpen = $("#open-new");
var $btnMenu = $("#open-menu");

// Update codebox.io connexion
var updateRemote = function() {
    var boxes, key, token;
    token = storage.get("token");

    $alert.toggle(!token);
    if (!token) {
        boxes = [];
        storage.set("remoteBoxes", boxes);
        updateProjects();
    }

    var client = new CodeboxIO({
        'host': codeboxIoHost,
        'token': token
    });
    client.account().then(function(account) {
        storage.set("email", account.email);
        return client.boxes()
    }).then(function(_boxes) {
        boxes = _.map(_boxes, function(box) {
            return _.pick(box, "name", "url", "stack", "id", "public", "permissions");
        });
        storage.set("remoteBoxes", boxes);
        updateProjects();
    });
};

// Add project item
var addProjectItem = function(name, description, image, handler) {
    var $project = $("
", {
        'class': "project",
        'click': handler
    });
    $("", {
        'src': image,
        'class': 'project-icon'
    }).appendTo($project);
    $("
", {
        'text': name,
        'class': 'project-title'
    }).appendTo($project);
    $("
", {
        'text': description,
        'class': 'project-path'
    }).appendTo($project);

    $projectList.append($project);
};

// Update list of projects
var updateProjects = function() {
    var projects = storage.get("projects", []);
    $projectList.empty();

    // Add remote boxes
    var boxes = storage.get("remoteBoxes", []);
    boxes.forEach(function(box) {
        addProjectItem(box.name, "remote - "+box.stack, "icons/128.png", function() {
            runRemoteCodebox(box);
        });
    });
    if (boxes.length > 0) {
        $projectList.append("
");
    }

    if (projects.length === 0) {
        $projectList.append($("
", {
            'class': "empty-message",
            'text': "No recent folders"
        }));
    }
    projects.reverse().forEach(function(path, i) {
        if (!fs.existsSync(path)) {
            projects = _.without(projects, path);
        }
        addProjectItem(path.split("/").pop(), path, "icons/folder.png", function() {
            runLocalCodebox(path);
        });
    });

    // Resave project
    storage.set("projects", projects);

    return projects.length > 0;
};

// Update codebox.io account
var updateCodeboxIOAccount = function() {
    var token = storage.get("token");

    if (token) {
        if (confirm("Do you want to unlink this desktop from your codebox.io account?") == true) {
            token = "";
        }
    } else {
        token = prompt("Please enter your codebox.io account token to connect it to this desktop, this token can be found on your codebox.io account settings:");
    }

    storage.set("token", token);
    updateRemote();
}

// Add a path to the projects list
var addProject = function(path) {
    if (!path) return false;

    var projects = storage.get("projects", []);

    // Project is already added
    if (projects.indexOf(path) !== -1) return false;

    projects.push(path);
    storage.set("projects", projects);
    updateProjects();

    return true;
};

// Select new project
var selectPath = function() {
    $directorySelector.click();
};

/*
    Extras support
*/

var addToPATH = function(binPath) {
    process.env.PATH = [binPath, process.env.PATH].join(':');
};

// Detect modules of extras folder and modify envs accordingly
var importExtras = function() {
    var extrasDir = path.resolve(path.join(
        require('./js/dirname').dirname, '..', '..', 'extras'
    ));

    // Skip if extras dir doesn't exist
    if(!fs.existsSync(extrasDir)) {
        return;
    }

    // Try importing each module
    fs.readdirSync(extrasDir).forEach(function(subDir) {
        return importExtra(path.join(extrasDir, subDir));
    });
};

// Import a specifc extra module
// (add bin subfolder to PATH, etc ...)
var importExtra = function(_path) {
    // Folder containing extra binaries
    var binPath = path.join(_path, 'bin');

    // Add it
    if(fs.existsSync(binPath)) {
        addToPATH(binPath);
    }
};

// Start the local ide for a path
var runLocalCodebox = function(path) {
    path = encodeURIComponent(path);
    var env = encodeURIComponent(JSON.stringify(process.env));
    var win = gui.Window.open("./ide.html?path="+path+"&env="+env, {
        'title': "Codebox",
        'position': 'center',
        'width': 1024,
        'height': 768,
        'min_height': 400,
        'min_width': 400,
        'show':false,
        'toolbar': false,
        'frame': true,
        'new-instance': true    // Because new isntance, we can't access the win object
    });
    win.maximize();
    return win;
};

// Open the remote ide for a box
var runRemoteCodebox = function(box) {
    var options = {
        'token': storage.get("token")
    };

    var url = box.url;
    if (navigator.onLine) url = codeboxIoHost+"/boot/"+box.id+"?"+querystring.stringify(options);

    var win = gui.Window.open(url, {
        'title': "Codebox",
        'position': 'center',
        'width': 1024,
        'height': 768,
        'min_height': 400,
        'min_width': 400,
        'show': true,
        'toolbar': false,
        'frame': true,
        'nodejs': false,
        'new-instance': false
    });
    win.maximize();
    return win;
};

// Bind events
$directorySelector.change(function handleFileSelect(evt) {
    var path = $(this).val();
    if (addProject(path)) runLocalCodebox(path);
});
$btnOpen.click(function(e) {
    e.preventDefault();
    selectPath();
});
$btnMenu.click(function(e) {
    e.preventDefault();
    var pos = $btnMenu.offset();

    var menu = new gui.Menu();
    var token = storage.get("token");

    if (token) {
        menu.append(new gui.MenuItem({
            label: 'Disconnect codebox.io account',
            click: function() {
                updateCodeboxIOAccount();
            }
        }));
    } else {
        menu.append(new gui.MenuItem({
            label: 'Connect codebox.io account',
            click: function() {
                updateCodeboxIOAccount();
            }
        }));
        menu.append(new gui.MenuItem({
            label: 'Sign up to codebox.io',
            click: function() {
                gui.Shell.openExternal(codeboxIoHost+'/signup');
            }
        }));
    }
    menu.append(new gui.MenuItem({ type: 'separator' }));

    menu.append(new gui.MenuItem({
        label: 'Reset all data',
        click: function() {
            localStorage.clear();
            updateRemote();
        }
    }));
    menu.append(new gui.MenuItem({ type: 'separator' }));
    menu.append(new gui.MenuItem({
        label: 'Quit',
        click: function() {
            gui.App.quit();
        }
    }));
    menu.popup(Math.floor(pos.left), Math.floor(pos.top));
});
$alert.click(function(e) {
    e.preventDefault();
    updateCodeboxIOAccount();
});

// Start the application
window.onload = function() {
    var win = gui.Window.get();

    // Show then focus
    win.show();
    win.focus();

    // Start
    updateRemote();
    if (!updateProjects()) {
        selectPath();
    }

    // Import extra modules
    importExtras();
};
<commit_msg>Add workspace name to local desktop window titles<commit_after>// Requires
var gui = require('nw.gui');

var Q = require('q');
var _ = require('lodash');

var fs = require('fs');
var path = require('path');
var querystring = require("querystring");

var CodeboxIO = require('codebox-io').Client;

// Local storage utilities
var storage = {
    get: function(key, def) {
        try {
            return JSON.parse(window.localStorage[key]);
        } catch(err) {
            return window.localStorage[key] || def;
        }
    },
        set: function(key, value) {
        window.localStorage[key] = JSON.stringify(value);
    }
};

// Config
var codeboxIoHost = "https://www.codebox.io";

// Port allocation
var qClass = require('qpatch').qClass;
var harbor = qClass(require('harbor'));
var ports = new harbor(19000, 20000);

// DOM elements
var $directorySelector = $('#directory-selector');
var $projectList = $('#projects');
var $alert = $("#body .alert");
var $btnOpen = $("#open-new");
var $btnMenu = $("#open-menu");

// Update codebox.io connexion
var updateRemote = function() {
    var boxes, key, token;
    token = storage.get("token");

    $alert.toggle(!token);
    if (!token) {
        boxes = [];
        storage.set("remoteBoxes", boxes);
        updateProjects();
    }

    var client = new CodeboxIO({
        'host': codeboxIoHost,
        'token': token
    });
    client.account().then(function(account) {
        storage.set("email", account.email);
        return client.boxes()
    }).then(function(_boxes) {
        boxes = _.map(_boxes, function(box) {
            return _.pick(box, "name", "url", "stack", "id", "public", "permissions");
        });
        storage.set("remoteBoxes", boxes);
        updateProjects();
    });
};

// Add project item
var addProjectItem = function(name, description, image, handler) {
    var $project = $("
", {
        'class': "project",
        'click': handler
    });
    $("", {
        'src': image,
        'class': 'project-icon'
    }).appendTo($project);
    $("
", {
        'text': name,
        'class': 'project-title'
    }).appendTo($project);
    $("
", {
        'text': description,
        'class': 'project-path'
    }).appendTo($project);

    $projectList.append($project);
};

// Update list of projects
var updateProjects = function() {
    var projects = storage.get("projects", []);
    $projectList.empty();

    // Add remote boxes
    var boxes = storage.get("remoteBoxes", []);
    boxes.forEach(function(box) {
        addProjectItem(box.name, "remote - "+box.stack, "icons/128.png", function() {
            runRemoteCodebox(box);
        });
    });
    if (boxes.length > 0) {
        $projectList.append("
");
    }

    if (projects.length === 0) {
        $projectList.append($("
", {
            'class': "empty-message",
            'text': "No recent folders"
        }));
    }
    projects.reverse().forEach(function(path, i) {
        if (!fs.existsSync(path)) {
            projects = _.without(projects, path);
        }
        addProjectItem(path.split("/").pop(), path, "icons/folder.png", function() {
            runLocalCodebox(path);
        });
    });

    // Resave project
    storage.set("projects", projects);

    return projects.length > 0;
};

// Update codebox.io account
var updateCodeboxIOAccount = function() {
    var token = storage.get("token");

    if (token) {
        if (confirm("Do you want to unlink this desktop from your codebox.io account?") == true) {
            token = "";
        }
    } else {
        token = prompt("Please enter your codebox.io account token to connect it to this desktop, this token can be found on your codebox.io account settings:");
    }

    storage.set("token", token);
    updateRemote();
}

// Add a path to the projects list
var addProject = function(path) {
    if (!path) return false;

    var projects = storage.get("projects", []);

    // Project is already added
    if (projects.indexOf(path) !== -1) return false;

    projects.push(path);
    storage.set("projects", projects);
    updateProjects();

    return true;
};

// Select new project
var selectPath = function() {
    $directorySelector.click();
};

/*
    Extras support
*/

var addToPATH = function(binPath) {
    process.env.PATH = [binPath, process.env.PATH].join(':');
};

// Detect modules of extras folder and modify envs accordingly
var importExtras = function() {
    var extrasDir = path.resolve(path.join(
        require('./js/dirname').dirname, '..', '..', 'extras'
    ));

    // Skip if extras dir doesn't exist
    if(!fs.existsSync(extrasDir)) {
        return;
    }

    // Try importing each module
    fs.readdirSync(extrasDir).forEach(function(subDir) {
        return importExtra(path.join(extrasDir, subDir));
    });
};

// Import a specifc extra module
// (add bin subfolder to PATH, etc ...)
var importExtra = function(_path) {
    // Folder containing extra binaries
    var binPath = path.join(_path, 'bin');

    // Add it
    if(fs.existsSync(binPath)) {
        addToPATH(binPath);
    }
};

// Start the local ide for a path
var runLocalCodebox = function(_path) {
    var encodedPath = encodeURIComponent(_path);
    var env = encodeURIComponent(JSON.stringify(process.env));
    var win = gui.Window.open("./ide.html?path="+encodedPath+"&env="+env, {
        'title': [path.basename(_path),  "Codebox"].join('-'),
        'position': 'center',
        'width': 1024,
        'height': 768,
        'min_height': 400,
        'min_width': 400,
        'show':false,
        'toolbar': false,
        'frame': true,
        'new-instance': true    // Because new isntance, we can't access the win object
    });
    win.maximize();
    return win;
};

// Open the remote ide for a box
var runRemoteCodebox = function(box) {
    var options = {
        'token': storage.get("token")
    };

    var url = box.url;
    if (navigator.onLine) url = codeboxIoHost+"/boot/"+box.id+"?"+querystring.stringify(options);

    var win = gui.Window.open(url, {
        'title': "Codebox",
        'position': 'center',
        'width': 1024,
        'height': 768,
        'min_height': 400,
        'min_width': 400,
        'show': true,
        'toolbar': false,
        'frame': true,
        'nodejs': false,
        'new-instance': false
    });
    win.maximize();
    return win;
};

// Bind events
$directorySelector.change(function handleFileSelect(evt) {
    var path = $(this).val();
    if (addProject(path)) runLocalCodebox(path);
});
$btnOpen.click(function(e) {
    e.preventDefault();
    selectPath();
});
$btnMenu.click(function(e) {
    e.preventDefault();
    var pos = $btnMenu.offset();

    var menu = new gui.Menu();
    var token = storage.get("token");

    if (token) {
        menu.append(new gui.MenuItem({
            label: 'Disconnect codebox.io account',
            click: function() {
                updateCodeboxIOAccount();
            }
        }));
    } else {
        menu.append(new gui.MenuItem({
            label: 'Connect codebox.io account',
            click: function() {
                updateCodeboxIOAccount();
            }
        }));
        menu.append(new gui.MenuItem({
            label: 'Sign up to codebox.io',
            click: function() {
                gui.Shell.openExternal(codeboxIoHost+'/signup');
            }
        }));
    }
    menu.append(new gui.MenuItem({ type: 'separator' }));

    menu.append(new gui.MenuItem({
        label: 'Reset all data',
        click: function() {
            localStorage.clear();
            updateRemote();
        }
    }));
    menu.append(new gui.MenuItem({ type: 'separator' }));
    menu.append(new gui.MenuItem({
        label: 'Quit',
        click: function() {
            gui.App.quit();
        }
    }));
    menu.popup(Math.floor(pos.left), Math.floor(pos.top));
});
$alert.click(function(e) {
    e.preventDefault();
    updateCodeboxIOAccount();
});

// Start the application
window.onload = function() {
    var win = gui.Window.get();

    // Show then focus
    win.show();
    win.focus();

    // Start
    updateRemote();
    if (!updateProjects()) {
        selectPath();
    }

    // Import extra modules
    importExtras();
};
<|endoftext|>


<commit_before>/*! Responsive Menu */
// http://tympanus.net/codrops/2013/05/08/responsive-retina-ready-menu/
//  The function to change the class
var changeClass = function (r,className1,className2) {
  var regex = new RegExp("(?:^|\\s+)" + className1 + "(?:\\s+|$)");
  if( regex.test(r.className) ) {
    r.className = r.className.replace(regex,' '+className2+' ');
    }
    else{
    r.className = r.className.replace(new RegExp("(?:^|\\s+)" + className2 + "(?:\\s+|$)"),' '+className1+' ');
    }
    return r.className;
};
//  Creating our button in JS for smaller screens
var menuElements = document.getElementById('site-nav');
menuElements.insertAdjacentHTML('afterBegin','<button type="button" role="button" id="menutoggle" class="navtoggle navicon-lines-button x" aria-hidden="true">menu</button>');

//  Toggle the class on click to show / hide the menu
document.getElementById('menutoggle').onclick = function() {
  changeClass(this, 'navtoggle active', 'navtoggle');
};
// http://tympanus.net/codrops/2013/05/08/responsive-retina-ready-menu/comment-page-2/#comment-438918
document.onclick = function(e) {
  var mobileButton = document.getElementById('menutoggle'),
    buttonStyle =  mobileButton.currentStyle ? mobileButton.currentStyle.display : getComputedStyle(mobileButton, null).display;

  if(buttonStyle === 'block' && e.target !== mobileButton && new RegExp(' ' + 'active' + ' ').test(' ' + mobileButton.className + ' ')) {
    changeClass(mobileButton, 'navtoggle active', 'navtoggle');
  }
};

/*! Plugin options and other jQuery stuff */

// FitVids options
$(function() {
	$("article").fitVids();
});

// Table of Contents toggle
$(function() {
  $(".toc h3").click(function () {
    $("#drawer").toggleClass("js-hidden");
  });
});

// Add lightbox class to all image links
$("a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif']").addClass("image-popup");

// Magnific-Popup options
$(document).ready(function() {
  $('.image-popup').magnificPopup({
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'Image #%curr% could not be loaded.',
    },
    removalDelay: 300, // Delay in milliseconds before popup is removed
    // Class that is added to body when popup is open.
    // make it unique to apply your CSS animations just to this exact popup
    mainClass: 'mfp-fade'
  });
});
<commit_msg>Update _main.js<commit_after>/*! Responsive Menu */
// http://tympanus.net/codrops/2013/05/08/responsive-retina-ready-menu/
//  The function to change the class
var changeClass = function (r,className1,className2) {
  var regex = new RegExp("(?:^|\\s+)" + className1 + "(?:\\s+|$)");
  if( regex.test(r.className) ) {
    r.className = r.className.replace(regex,' '+className2+' ');
    }
    else{
    r.className = r.className.replace(new RegExp("(?:^|\\s+)" + className2 + "(?:\\s+|$)"),' '+className1+' ');
    }
    return r.className;
};
//  Creating our button in JS for smaller screens
var menuElements = document.getElementById('site-nav');
menuElements.insertAdjacentHTML('afterBegin','<button type="button" role="button" id="menutoggle" class="navtoggle navicon-lines-button x" aria-hidden="true">menu</button>');

//  Toggle the class on click to show / hide the menu
document.getElementById('menutoggle').onclick = function() {
  changeClass(this, 'navtoggle active', 'navtoggle');
};
// http://tympanus.net/codrops/2013/05/08/responsive-retina-ready-menu/comment-page-2/#comment-438918
document.onclick = function(e) {
  var mobileButton = document.getElementById('menutoggle'),
    buttonStyle =  mobileButton.currentStyle ? mobileButton.currentStyle.display : getComputedStyle(mobileButton, null).display;

  if(buttonStyle === 'block' && e.target !== mobileButton && new RegExp(' ' + 'active' + ' ').test(' ' + mobileButton.className + ' ')) {
    changeClass(mobileButton, 'navtoggle active', 'navtoggle');
  }
};

/*! Plugin options and other jQuery stuff */

// FitVids options
$(function() {
	$("article").fitVids();
});

// Table of Contents toggle
$(function() {
  $(".toc h3").click(function () {
    $("#drawer").toggleClass("js-hidden");
  });
});

// Add lightbox class to all image links
$("a[href$='.jpg'],a[href$='.jpeg'],a[href$='.JPG'],a[href$='.png'],a[href$='.gif']").addClass("image-popup");

// Magnific-Popup options
$(document).ready(function() {
  $('.image-popup').magnificPopup({
    type: 'image',
    tLoading: 'Loading image #%curr%...',
    gallery: {
      enabled: true,
      navigateByImgClick: true,
      preload: [0,1] // Will preload 0 - before current, and 1 after the current image
    },
    image: {
      tError: 'Image #%curr% could not be loaded.',
    },
    removalDelay: 300, // Delay in milliseconds before popup is removed
    // Class that is added to body when popup is open.
    // make it unique to apply your CSS animations just to this exact popup
    mainClass: 'mfp-fade'
  });
});
(function () {
  var newMathJax = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js';
  var oldMathJax = 'cdn.mathjax.org/mathjax/latest/MathJax.js';

  var replaceScript = function (script, src) {
    //
    //  Make redirected script
    //
    var newScript = document.createElement('script');
    newScript.src = newMathJax + src.replace(/.*?(\?|$)/, '$1');
    //
    //  Move onload and onerror handlers to new script
    //
    newScript.onload = script.onload;
    newScript.onerror = script.onerror;
    script.onload = script.onerror = null;
    //
    //  Move any content (old-style configuration scripts)
    //
    while (script.firstChild) newScript.appendChild(script.firstChild);
    //
    //  Copy script id
    //
    if (script.id != null) newScript.id = script.id;
    //
    //  Replace original script with new one
    //
    script.parentNode.replaceChild(newScript, script);
    //
    //  Issue a console warning
    //
    console.warn('WARNING: cdn.mathjax.org has been retired. Check https://www.mathjax.org/cdn-shutting-down/ for migration tips.')
  }

  if (document.currentScript) {
    var script = document.currentScript;
    replaceScript(script, script.src);
  } else {
    //
    // Look for current script by searching for one with the right source
    //
    var n = oldMathJax.length;
    var scripts = document.getElementsByTagName('script');
    for (var i = 0; i < scripts.length; i++) {
      var script = scripts[i];
      var src = (script.src || '').replace(/.*?:\/\//,'');
      if (src.substr(0, n) === oldMathJax) {
        replaceScript(script, src);
        break;
      }
    }
  }
})();
<|endoftext|>


<commit_before>/*   Riassence Framework
 *   Copyright 2007 Riassence Inc.
 *   http://riassence.com/
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this software package. If not, contact licensing@riassence.com
 */

JSLoader = HClass.extend({

  constructor: function(_uri){
    var _this = this;
    _this._loadedJS = [];
    _this.uri  = _uri;
    _this._okayed = false;
  },

  _fail: function(_this,_resp){
    console.log("failed to load js: "+_resp.url);
  },

  load: function(_jsName){
    var _this = this;
    if((_this._loadedJS.indexOf(_jsName)!==-1)) {
      return;
    }
    COMM.Queue.pause();
    _this._loadedJS.push(_jsName);
    _this._req = COMM.request(
      _this.uri+_jsName+'.js', {
        onSuccess: function(_resp){
          COMM.Queue.unshiftEval(_resp.X.responseText);
          COMM.Queue.resume();
        },
        onFailure: _this._fail,
        method: 'GET',
        async: true
      }
    );
  }

});

RUN("jsLoader = JSLoader.nu(HCLIENT_BASE+'/js/');");

<commit_msg>Documentation<commit_after>/*   Riassence Framework
 *   Copyright 2007 Riassence Inc.
 *   http://riassence.com/
 *
 *   You should have received a copy of the GNU General Public License along
 *   with this software package. If not, contact licensing@riassence.com
 */

/*** = Description
  ** A class for asynchronously fetching Javascript libraries from the server.
  **
  ** Loads and evalueates the code returned as a string from the server.
  ** Use the jsLoader instance to get packaged Javascript libraries from the
  ** standard package url.
***/
JSLoader = HClass.extend({

/** = Description
  * Construct with the base url.
  *
  * The this is the base url used by the +load+ method.
  *
  **/
  constructor: function(_uri){
    var _this = this;
    _this._loadedJS = [];
    _this.uri  = _uri;
    _this._okayed = false;
  },

  // Error catcher for failed requests.
  _fail: function(_this,_resp){
    console.log("failed to load js: "+_resp.url);
  },

/** = Description
  * Loads a js package using the name.
  *
  * The base url given in the constructor is used as the prefix.
  * Omit the '.js' suffix, because it's appended automatically.
  *
  * = Parameters
  * +_jsName+::   The name of the js file to load (without the .js suffix)
  *
  * = Usage:
  * Uses the main instance set to the base path of the server's
  * js package url. Loads a package containing list components.
  *   jsLoader.load('lists');
  *
  **/
  load: function(_jsName){
    var _this = this;
    if((_this._loadedJS.indexOf(_jsName)!==-1)) {
      return;
    }
    COMM.Queue.pause();
    _this._loadedJS.push(_jsName);
    _this._req = COMM.request(
      _this.uri+_jsName+'.js', {
        onSuccess: function(_resp){
          COMM.Queue.unshiftEval(_resp.X.responseText);
          COMM.Queue.resume();
        },
        onFailure: _this._fail,
        method: 'GET',
        async: true
      }
    );
  }

});

// Makes the standard jsLoader instance based on the client base url
// of the server when the page is loaded.
RUN("jsLoader = JSLoader.nu(HCLIENT_BASE+'/js/');");

<|endoftext|>