<commit_before>/*:
 * RS_MultipleViewports.js
 * @plugindesc (v1.1.8) This plugin provides the multiple viewports.
 * @author biud436
 *
 * @help
 * -----------------------------------------------------------------------------
 * Plugin Commands
 * -----------------------------------------------------------------------------
 *
 * This is a plugin command that this can activate the multiple viewports.
 * If you call this plugin command, You can be using the multiple viewports.
 * - MultipleViewport Enable
 *
 * This can disable the multiple viewports.
 * If you call this plugin command, You can be using original stage renderer.
 * - MultipleViewport Disable
 *
 * This is the plugin command you can set the power of the viewport shake.
 * - MultipleViewport StartShake shakePower
 *
 * This is the plugin command you can set the end of the viewport shake.
 * - MultipleViewport EndShake
 *
 * This is the plugin command you can set an image to certain viewport.
 * (View ID is number between 1 and 4)
 * - MultipleViewport Image ViewID ImageName
 *
 * This is the plugin command you can delete the image to certain viewport.
 * (View ID is number between 1 and 4)
 * - MultipleViewport ClearImage ViewID
 *
 * This is the plugin command that can set the video to certain viewport.
 * Note that the file type should set the WEBM(.webm)
 * ViewID is the number between 1 and 4.
 * szSrc Indicates an video name from the movies directory.
 * loop allows you to set with the true or false.
 * You can repeat the video via this value. (If you are omitted this loop value, its video will only play once.)
 *
 * - MultipleViewport Video viewID szSrc loop
 *
 * This command moves back x seconds from current video position.
 * - MultipleViewport MoveBackSeconds viewID second
 *
 * This command moves forward x seconds from current video position.
 * - MultipleViewport MoveForwardSeconds viewID second
 *
 * This is the plugin command can play the video to certain viewport.
 * - MultipleViewport PlayVideo viewID
 *
 * This is the plugin command can stop the video to certain viewport.
 * - MultipleViewport StopVideo viewID
 *
 * This is the plugin command can pause the video to certain viewport.
 * - MultipleViewport PauseVideo viewID
 *
 * This is the plugin command can remove the video to certain viewport.
 * - MultipleViewport ClearVideo viewID
 *
 * -----------------------------------------------------------------------------
 * Changle Log
 * -----------------------------------------------------------------------------
 * 2016.06.13 (v1.0.0) - First Release.
 * 2016.08.24 (v1.1.0) - Now RPG Maker MV 1.3.0 or more is supported.
 * 2016.08.24 (v1.1.2) - Added Plugin Commands
 * 2016.08.25 (v1.1.4) - Added the functions that sets an image of certain viewport.
 * 2016.09.30 (v1.1.5) - Added the function that plays an video of certain viewport.
 * 2016.10.01 (v1.1.6) - Added the rendering code that is compatible with the canvas mode.
 * 2016.10.20 (v1.1.7) - Fixed the issue that is not working in RMMV 1.3.2
 * 2016.10.23 (v1.1.8) - Fixed PIXI.VideoBaseTexture update issue in PIXI 4.0.3
 */

var Imported = Imported || {};
Imported.RS_MultipleViewports = true;

(function () {

  var isFilterPIXI4 = (PIXI.VERSION >= "4.0.0" && Utils.RPGMAKER_VERSION >= "1.3.0");

  var isMultipleViewport = false;
  var isShake = 0;
  var shakePower = 10;

  //============================================================================
  // PIXI v4.0.3 Bug Fixes
  //============================================================================

  var ticker = PIXI.ticker;

  PIXI.VideoBaseTexture.prototype._onPlayStart = function _onPlayStart() {
      // Just in case the video has not recieved its can play even yet..
      if (!this.hasLoaded) {
          this._onCanPlay();
      }

      if (!this._isAutoUpdating && this.autoUpdate) {
          ticker.shared.add(this.update, this);
          ticker.shared.stop();
          ticker.shared.start();
          this._isAutoUpdating = true;

      }
  };

  //============================================================================
  // Graphics
  //============================================================================

  Graphics.getRenderPosition = function(width, height) {
    var positionType = [];
    positionType[0] = new Rectangle(0, 0, width / 2, height / 2);
    positionType[1] = new Rectangle(width / 2, 0, width / 2, height / 2);
    positionType[2] = new Rectangle(0, height / 2, width / 2, height / 2);
    positionType[3] = new Rectangle(width / 2, height / 2, width / 2, height / 2);
    return positionType;
  };

  var alias_Graphics__createRenderer = Graphics._createRenderer;
  Graphics._createRenderer = function() {
    alias_Graphics__createRenderer.call(this);
    this._createRenderTexture();
  };

  Graphics._createRenderTexture = function () {
    var sprite; var rect; var self = Graphics;
    if(!self._renderer) { return; }
    if(this.isWebGL()) var gl = self._renderer.gl;
    self._renderSprite = [];

    // Calculrate Screen
    if(this.isWebGL()) {
      self._frameWidth = gl.drawingBufferWidth || 816;
      self._frameHeight = gl.drawingBufferHeight || 624;
    } else {
      self._frameWidth = self._renderer.width || 816;
      self._frameHeight = self._renderer.height || 624;
    }

    // Create RenderTexture
    self._renderTexture = PIXI.RenderTexture.create(self._frameWidth,
                                                    self._frameHeight,
                                                    PIXI.SCALE_MODES.NEAREST);

    // Create Rect
    self._rect = self.getRenderPosition(self._frameWidth, self._frameHeight);

    // Create RenderTarget
    if(this.isWebGL()) {
      self._renderTarget = new PIXI.RenderTarget(gl, self._frameWidth,
                                                    self._frameHeight,
                                                    PIXI.SCALE_MODES.NEAREST);
    } else {
      self._renderTarget = new PIXI.CanvasRenderTarget(self._frameWidth, self._frameHeight);
    }

    // Create Sprite
    self._renderSprite = new Sprite();

    // Add Child Sprite
    for(var i = 0; i < 4; i++) {
      self._renderSprite.addChild(new Sprite());
    }

    self._viewImageCached = [];

    self._renderBounds = new Rectangle(0, 0, self._frameWidth, self._frameHeight);

  }

  Graphics.setRenderSprite = function (i) {
    var sPower = shakePower * isShake;
    var shake = (-0.5 + Math.random()) * sPower;
    this._renderSprite.children[i].x = this._rect[i].x + shake;
    this._renderSprite.children[i].y = this._rect[i].y + shake;
    if(Graphics.isCheckedViewImage(i)) {
      var texture = this._renderSprite.children[i].texture = this._viewImageCached[i];
      this._renderSprite.children[i].scale.x = (Graphics.boxWidth / texture.width) * 0.5;
      this._renderSprite.children[i].scale.y = (Graphics.boxHeight / texture.height) * 0.5;
    } else {
      this._renderSprite.children[i].texture = this._renderTexture;
      this._renderSprite.children[i].scale.x = 0.5;
      this._renderSprite.children[i].scale.y = 0.5;
    }
  };

  Graphics.setViewportImage = function (viewID, texture) {
    if(this._viewImageCached[viewID - 1]) {
      this._viewImageCached[viewID - 1] = null;
    }
    this._viewImageCached[viewID - 1] = texture;
  };

  Graphics.moveMoviesToCertainView = function (viewID, funcName, second) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      switch (funcName) {
        case 'Move Back':
          video.currentTime -= second;
          break;
        case 'Move Forward':
          video.currentTime += second;
          break;
      }
    }
  };

  Graphics.playMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.play();
    }
  };

  Graphics.pauseMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.pause();
    }
  };

  Graphics.stopMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.pause();
      video.currentTime = 0.0;
    }
  };

  Graphics.pauseAllMovies = function () {
    this._viewImageCached.forEach(function (i) {
      if(i.baseTexture instanceof PIXI.VideoBaseTexture) i.baseTexture.source.pause();
    })
  };

  Graphics.playAllMovies = function () {
    this._viewImageCached.forEach(function (i) {
      if(i.baseTexture instanceof PIXI.VideoBaseTexture) i.baseTexture.source.play();
    })
  };

  Graphics.isCheckedViewImage = function (viewID) {
    var texture = this._viewImageCached[viewID];
    if(texture instanceof PIXI.Texture) {
      return !!texture.baseTexture && texture.baseTexture.hasLoaded;
    } else {
      return false;
    }
  };

  Graphics.clearViewImage = function (viewID) {
    if(this._viewImageCached[viewID - 1]) {
        delete this._viewImageCached[viewID - 1];
    }
  };

  Graphics.render = function(stage) {
    if (this._skipCount === 0) {
        var startTime = Date.now();
        if (stage) {
          if(isMultipleViewport) {
            if(this.isWebGL()) this._renderer.bindRenderTexture(this._renderTexture);
            this._renderer.render(stage, this._renderTexture);
            if(this.isWebGL()) this._renderer.bindRenderTarget(this._renderTarget);
            for(var i = 0; i < 4; i++) this.setRenderSprite(i);
            this._renderer.render(this._renderSprite);
          } else {
            this._renderer.render(stage);
          }
        }
        var endTime = Date.now();
        var elapsed = endTime - startTime;
        this._skipCount = Math.min(Math.floor(elapsed / 15), this._maxSkip);
        this._rendered = true;
    } else {
        this._skipCount--;
        this._rendered = false;
    }
    this.frameCount++;
  };

  //============================================================================
  // Game_Interpreter
  //============================================================================

  var alias_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
      alias_Game_Interpreter_pluginCommand.call(this, command, args);
      if(command === "MultipleViewport") {
        switch(args[0]) {
          case 'Enable':
            isMultipleViewport = true;
            Graphics.playAllMovies();
            break;
          case 'Disable':
            isMultipleViewport = false;
            Graphics.pauseAllMovies();
            break;
          case 'StartShake':
            isShake = 1;
            shakePower = Number(args[1] || 10);
            break;
          case 'EndShake':
            isShake = 0;
            break;
          case 'Image':
            var viewID = Number(args[1] || 1);
            var name = args.slice(2, args.length).join(' ');
            var imageName = 'img/pictures/' + name + '.png';
            var texture = PIXI.Texture.fromImage(imageName);
            Graphics.setViewportImage(viewID.clamp(1, 4), texture);
            break;
          case 'ClearImage':
            Graphics.clearViewImage(Number(args[1]));
            break;
          case 'Video':
            var viewID = Number(args[1] || 1);
            var name = args[2];
            var looping = (args[3] === 'true');
            var videoName = 'movies/' + name + '.webm';
            var texture = PIXI.Texture.fromVideo(videoName);
            texture.baseTexture.source.loop = looping;
            Graphics.setViewportImage(viewID.clamp(1, 4), texture);
            break;
          case 'PlayVideo':
            var viewID = Number(args[1] || 1);
            Graphics.playMoviesToCertainView(viewID);
            break;
          case 'PauseVideo':
            var viewID = Number(args[1] || 1);
            Graphics.pauseMoviesToCertainView(viewID);
            break;
          case 'MoveBackSeconds':
            var viewID = Number(args[1] || 1);
            var sec = parseInt(args[2] || 0);
            Graphics.moveMoviesToCertainView(viewID, 'Move Back', sec);
            break;
          case 'MoveForwardSeconds':
            var viewID = Number(args[1] || 1);
            var sec = parseInt(args[2] || 0);
            Graphics.moveMoviesToCertainView(viewID, 'Move Forward', sec);
            break;
          case 'StopVideo':
            var viewID = Number(args[1] || 1);
            Graphics.stopMoviesToCertainView(viewID);
            break;
          case 'ClearVideo':
            var viewID = Number(args[1] || 1);
            Graphics.stopMoviesToCertainView(viewID);
            Graphics.clearViewImage(viewID);
            break;
        }
      }
  };

})();
<commit_msg>Fixed the issue that the video frame is not updated in PIXI 4.0.3<commit_after>/*:
 * RS_MultipleViewports.js
 * @plugindesc (v1.1.8) This plugin provides the multiple viewports.
 * @author biud436
 *
 * @help
 * -----------------------------------------------------------------------------
 * Plugin Commands
 * -----------------------------------------------------------------------------
 *
 * This is a plugin command that this can activate the multiple viewports.
 * If you call this plugin command, You can be using the multiple viewports.
 * - MultipleViewport Enable
 *
 * This can disable the multiple viewports.
 * If you call this plugin command, You can be using original stage renderer.
 * - MultipleViewport Disable
 *
 * This is the plugin command you can set the power of the viewport shake.
 * - MultipleViewport StartShake shakePower
 *
 * This is the plugin command you can set the end of the viewport shake.
 * - MultipleViewport EndShake
 *
 * This is the plugin command you can set an image to certain viewport.
 * (View ID is number between 1 and 4)
 * - MultipleViewport Image ViewID ImageName
 *
 * This is the plugin command you can delete the image to certain viewport.
 * (View ID is number between 1 and 4)
 * - MultipleViewport ClearImage ViewID
 *
 * This is the plugin command that can set the video to certain viewport.
 * Note that the file type should set the WEBM(.webm)
 * ViewID is the number between 1 and 4.
 * szSrc Indicates an video name from the movies directory.
 * loop allows you to set with the true or false.
 * You can repeat the video via this value. (If you are omitted this loop value, its video will only play once.)
 *
 * - MultipleViewport Video viewID szSrc loop
 *
 * This command moves back x seconds from current video position.
 * - MultipleViewport MoveBackSeconds viewID second
 *
 * This command moves forward x seconds from current video position.
 * - MultipleViewport MoveForwardSeconds viewID second
 *
 * This is the plugin command can play the video to certain viewport.
 * - MultipleViewport PlayVideo viewID
 *
 * This is the plugin command can stop the video to certain viewport.
 * - MultipleViewport StopVideo viewID
 *
 * This is the plugin command can pause the video to certain viewport.
 * - MultipleViewport PauseVideo viewID
 *
 * This is the plugin command can remove the video to certain viewport.
 * - MultipleViewport ClearVideo viewID
 *
 * -----------------------------------------------------------------------------
 * Changle Log
 * -----------------------------------------------------------------------------
 * 2016.06.13 (v1.0.0) - First Release.
 * 2016.08.24 (v1.1.0) - Now RPG Maker MV 1.3.0 or more is supported.
 * 2016.08.24 (v1.1.2) - Added Plugin Commands
 * 2016.08.25 (v1.1.4) - Added the functions that sets an image of certain viewport.
 * 2016.09.30 (v1.1.5) - Added the function that plays an video of certain viewport.
 * 2016.10.01 (v1.1.6) - Added the rendering code that is compatible with the canvas mode.
 * 2016.10.20 (v1.1.7) - Fixed the issue that is not working in RMMV 1.3.2
 * 2016.10.23 (v1.1.8) - Fixed the issue that the video frame is not updated in PIXI 4.0.3
 */

var Imported = Imported || {};
Imported.RS_MultipleViewports = true;

(function () {

  var isFilterPIXI4 = (PIXI.VERSION >= "4.0.0" && Utils.RPGMAKER_VERSION >= "1.3.0");

  var isMultipleViewport = false;
  var isShake = 0;
  var shakePower = 10;

  //============================================================================
  // PIXI v4.0.3 Bug Fixes
  //============================================================================

  var ticker = PIXI.ticker;

  PIXI.VideoBaseTexture.prototype._onPlayStart = function _onPlayStart() {
      // Just in case the video has not recieved its can play even yet..
      if (!this.hasLoaded) {
          this._onCanPlay();
      }

      if (!this._isAutoUpdating && this.autoUpdate) {
          ticker.shared.add(this.update, this);
          ticker.shared.stop();
          ticker.shared.start();
          this._isAutoUpdating = true;

      }
  };

  //============================================================================
  // Graphics
  //============================================================================

  Graphics.getRenderPosition = function(width, height) {
    var positionType = [];
    positionType[0] = new Rectangle(0, 0, width / 2, height / 2);
    positionType[1] = new Rectangle(width / 2, 0, width / 2, height / 2);
    positionType[2] = new Rectangle(0, height / 2, width / 2, height / 2);
    positionType[3] = new Rectangle(width / 2, height / 2, width / 2, height / 2);
    return positionType;
  };

  var alias_Graphics__createRenderer = Graphics._createRenderer;
  Graphics._createRenderer = function() {
    alias_Graphics__createRenderer.call(this);
    this._createRenderTexture();
  };

  Graphics._createRenderTexture = function () {
    var sprite; var rect; var self = Graphics;
    if(!self._renderer) { return; }
    if(this.isWebGL()) var gl = self._renderer.gl;
    self._renderSprite = [];

    // Calculrate Screen
    if(this.isWebGL()) {
      self._frameWidth = gl.drawingBufferWidth || 816;
      self._frameHeight = gl.drawingBufferHeight || 624;
    } else {
      self._frameWidth = self._renderer.width || 816;
      self._frameHeight = self._renderer.height || 624;
    }

    // Create RenderTexture
    self._renderTexture = PIXI.RenderTexture.create(self._frameWidth,
                                                    self._frameHeight,
                                                    PIXI.SCALE_MODES.NEAREST);

    // Create Rect
    self._rect = self.getRenderPosition(self._frameWidth, self._frameHeight);

    // Create RenderTarget
    if(this.isWebGL()) {
      self._renderTarget = new PIXI.RenderTarget(gl, self._frameWidth,
                                                    self._frameHeight,
                                                    PIXI.SCALE_MODES.NEAREST);
    } else {
      self._renderTarget = new PIXI.CanvasRenderTarget(self._frameWidth, self._frameHeight);
    }

    // Create Sprite
    self._renderSprite = new Sprite();

    // Add Child Sprite
    for(var i = 0; i < 4; i++) {
      self._renderSprite.addChild(new Sprite());
    }

    self._viewImageCached = [];

    self._renderBounds = new Rectangle(0, 0, self._frameWidth, self._frameHeight);

  }

  Graphics.setRenderSprite = function (i) {
    var sPower = shakePower * isShake;
    var shake = (-0.5 + Math.random()) * sPower;
    this._renderSprite.children[i].x = this._rect[i].x + shake;
    this._renderSprite.children[i].y = this._rect[i].y + shake;
    if(Graphics.isCheckedViewImage(i)) {
      var texture = this._renderSprite.children[i].texture = this._viewImageCached[i];
      this._renderSprite.children[i].scale.x = (Graphics.boxWidth / texture.width) * 0.5;
      this._renderSprite.children[i].scale.y = (Graphics.boxHeight / texture.height) * 0.5;
    } else {
      this._renderSprite.children[i].texture = this._renderTexture;
      this._renderSprite.children[i].scale.x = 0.5;
      this._renderSprite.children[i].scale.y = 0.5;
    }
  };

  Graphics.setViewportImage = function (viewID, texture) {
    if(this._viewImageCached[viewID - 1]) {
      this._viewImageCached[viewID - 1] = null;
    }
    this._viewImageCached[viewID - 1] = texture;
  };

  Graphics.moveMoviesToCertainView = function (viewID, funcName, second) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      switch (funcName) {
        case 'Move Back':
          video.currentTime -= second;
          break;
        case 'Move Forward':
          video.currentTime += second;
          break;
      }
    }
  };

  Graphics.playMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.play();
    }
  };

  Graphics.pauseMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.pause();
    }
  };

  Graphics.stopMoviesToCertainView = function (viewID) {
    var texture = this._viewImageCached[viewID - 1];
    if(texture && texture.baseTexture instanceof PIXI.VideoBaseTexture) {
      var video = texture.baseTexture.source;
      video.pause();
      video.currentTime = 0.0;
    }
  };

  Graphics.pauseAllMovies = function () {
    this._viewImageCached.forEach(function (i) {
      if(i.baseTexture instanceof PIXI.VideoBaseTexture) i.baseTexture.source.pause();
    })
  };

  Graphics.playAllMovies = function () {
    this._viewImageCached.forEach(function (i) {
      if(i.baseTexture instanceof PIXI.VideoBaseTexture) i.baseTexture.source.play();
    })
  };

  Graphics.isCheckedViewImage = function (viewID) {
    var texture = this._viewImageCached[viewID];
    if(texture instanceof PIXI.Texture) {
      return !!texture.baseTexture && texture.baseTexture.hasLoaded;
    } else {
      return false;
    }
  };

  Graphics.clearViewImage = function (viewID) {
    if(this._viewImageCached[viewID - 1]) {
        delete this._viewImageCached[viewID - 1];
    }
  };

  Graphics.render = function(stage) {
    if (this._skipCount === 0) {
        var startTime = Date.now();
        if (stage) {
          if(isMultipleViewport) {
            if(this.isWebGL()) this._renderer.bindRenderTexture(this._renderTexture);
            this._renderer.render(stage, this._renderTexture);
            if(this.isWebGL()) this._renderer.bindRenderTarget(this._renderTarget);
            for(var i = 0; i < 4; i++) this.setRenderSprite(i);
            this._renderer.render(this._renderSprite);
          } else {
            this._renderer.render(stage);
          }
        }
        var endTime = Date.now();
        var elapsed = endTime - startTime;
        this._skipCount = Math.min(Math.floor(elapsed / 15), this._maxSkip);
        this._rendered = true;
    } else {
        this._skipCount--;
        this._rendered = false;
    }
    this.frameCount++;
  };

  //============================================================================
  // Game_Interpreter
  //============================================================================

  var alias_Game_Interpreter_pluginCommand = Game_Interpreter.prototype.pluginCommand;
  Game_Interpreter.prototype.pluginCommand = function(command, args) {
      alias_Game_Interpreter_pluginCommand.call(this, command, args);
      if(command === "MultipleViewport") {
        switch(args[0]) {
          case 'Enable':
            isMultipleViewport = true;
            Graphics.playAllMovies();
            break;
          case 'Disable':
            isMultipleViewport = false;
            Graphics.pauseAllMovies();
            break;
          case 'StartShake':
            isShake = 1;
            shakePower = Number(args[1] || 10);
            break;
          case 'EndShake':
            isShake = 0;
            break;
          case 'Image':
            var viewID = Number(args[1] || 1);
            var name = args.slice(2, args.length).join(' ');
            var imageName = 'img/pictures/' + name + '.png';
            var texture = PIXI.Texture.fromImage(imageName);
            Graphics.setViewportImage(viewID.clamp(1, 4), texture);
            break;
          case 'ClearImage':
            Graphics.clearViewImage(Number(args[1]));
            break;
          case 'Video':
            var viewID = Number(args[1] || 1);
            var name = args[2];
            var looping = (args[3] === 'true');
            var videoName = 'movies/' + name + '.webm';
            var texture = PIXI.Texture.fromVideo(videoName);
            texture.baseTexture.source.loop = looping;
            Graphics.setViewportImage(viewID.clamp(1, 4), texture);
            break;
          case 'PlayVideo':
            var viewID = Number(args[1] || 1);
            Graphics.playMoviesToCertainView(viewID);
            break;
          case 'PauseVideo':
            var viewID = Number(args[1] || 1);
            Graphics.pauseMoviesToCertainView(viewID);
            break;
          case 'MoveBackSeconds':
            var viewID = Number(args[1] || 1);
            var sec = parseInt(args[2] || 0);
            Graphics.moveMoviesToCertainView(viewID, 'Move Back', sec);
            break;
          case 'MoveForwardSeconds':
            var viewID = Number(args[1] || 1);
            var sec = parseInt(args[2] || 0);
            Graphics.moveMoviesToCertainView(viewID, 'Move Forward', sec);
            break;
          case 'StopVideo':
            var viewID = Number(args[1] || 1);
            Graphics.stopMoviesToCertainView(viewID);
            break;
          case 'ClearVideo':
            var viewID = Number(args[1] || 1);
            Graphics.stopMoviesToCertainView(viewID);
            Graphics.clearViewImage(viewID);
            break;
        }
      }
  };

})();
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

utils.platform = (function () {
  let platform = {}

  const userAgent = (navigator.userAgent).toLowerCase()
  const language = navigator.language || navigator.browserLanguage

  const version = platform.version = (userAgent.match(/.*(?:rv|chrome|webkit|opera|ie)[/: ](.+?)([ );]|$)/) || [])[1]
  const webkitVersion = (userAgent.match(/webkit\/(.+?) /) || [])[1]

  platform.windows = platform.isWindows = !!/windows/.test(userAgent)
  platform.mac = platform.isMac = !!/macintosh/.test(userAgent) || (/mac os x/.test(userAgent) && !/like mac os x/.test(userAgent))
  platform.lion = platform.isLion = !!(/mac os x 10_7/.test(userAgent) && !/like mac os x 10_7/.test(userAgent))
  platform.iPhone = platform.isiPhone = !!/iphone/.test(userAgent)
  platform.iPod = platform.isiPod = !!/ipod/.test(userAgent)
  platform.iPad = platform.isiPad = !!/ipad/.test(userAgent)
  platform.iOS = platform.isiOS = platform.iPhone || platform.iPod || platform.iPad
  platform.android = platform.isAndroid = !!/android/.test(userAgent)
  platform.opera = /opera/.test(userAgent) ? version : 0
  platform.isOpera = !!platform.opera
  platform.msie = /msie/.test(userAgent) && !platform.opera ? version : 0
  platform.isIE = !!platform.msie
  platform.isIE8OrLower = !!(platform.msie && parseInt(platform.msie, 10) <= 8)
  platform.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit|msie)/.test(userAgent) ? version : 0
  platform.isMozilla = !!platform.mozilla
  platform.webkit = /webkit/.test(userAgent) ? webkitVersion : 0
  platform.isWebkit = !!platform.webkit
  platform.chrome = /chrome/.test(userAgent) ? version : 0
  platform.isChrome = !!platform.chrome
  platform.mobileSafari = /apple.*mobile/.test(userAgent) && platform.iOS ? webkitVersion : 0
  platform.isMobileSafari = !!platform.mobileSafari
  platform.iPadSafari = platform.iPad && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPadSafari = !!platform.iPadSafari
  platform.iPhoneSafari = platform.iPhone && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPhoneSafari = !!platform.iphoneSafari
  platform.iPodSafari = platform.iPod && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPodSafari = !!platform.iPodSafari
  platform.isiOSHomeScreen = platform.isMobileSafari && !/apple.*mobile.*safari/.test(userAgent)
  platform.safari = platform.webkit && !platform.chrome && !platform.iOS && !platform.android ? webkitVersion : 0
  platform.isSafari = !!platform.safari
  platform.language = language.split('-', 1)[0]
  platform.current =
    platform.msie ? 'msie' : platform.mozilla ? 'mozilla' : platform.chrome ? 'chrome' : platform.safari ? 'safari' : platform.opera ? 'opera' : platform.mobileSafari ? 'mobile-safari' : platform.android ? 'android' : 'unknown'

  function platformName(candidates) {
    for (let i = 0; i < candidates.length; i++) {
      if (candidates[i] in window) {
        return 'window.' + candidates[i]
      }
      if (candidates[i] in navigator) {
        return 'navigator.' + candidates[i]
      }
    }
    return undefined
  }

  platform.GUM = platformName(['getUserMedia', 'webkitGetUserMedia', 'mozGetUserMedia', 'msGetUserMedia', 'getGUM'])
  platform.PeerConnection = platformName(['webkitRTCPeerConnection', 'mozRTCPeerConnection', 'msPeerConnection'])
  platform.IceCandidate = platformName(['mozRTCIceCandidate', 'RTCIceCandidate'])
  platform.SessionDescription = platformName(['mozRTCSessionDescription', 'RTCSessionDescription'])
  platform.URL = platformName(['URL', 'webkitURL'])
  platform.AudioContext = platformName(['AudioContext', 'webkitAudioContext'])
  platform.OfflineAudioContext = platformName(['OfflineAudioContext', 'webkitOfflineAudioContext'])
  platform.MediaSource = platformName(['MediaSource', 'WebKitMediaSource'])

  platform.SpeechRecognition = platformName(['SpeechRecognition', 'webkitSpeechRecognition'])
  platform.SpeechGrammarList = platformName(['SpeechGrammarList', 'webkitSpeechGrammarList'])

  /*
   function findWebGLContextName (candidates) {
   var canvas = document.createElement('canvas')
   for (var i = 0; i < candidates.length; i++) {
   var name = candidates[i]
   try {
   if (canvas.getContext(name)) {
   return name
   }
   } catch (e) {}
   }
   return null
   }
   */

  platform.WebGL = 'webgl' // findWebGLContextName(["webgl", "experimental-webgl", "webkit-3d"]);
  platform.WebGL2 = 'webgl2' // findWebGLContextName(["webgl2", "experimental-webgl2"]);

  platform.captureStreamUntilEnded = 'captureStreamUntilEnded'
  if (platform.isMozilla) {
    platform.captureStreamUntilEnded = 'mozCaptureStreamUntilEnded'
  }

  platform.srcObject = 'srcObject'
  if (platform.isMozilla) {
    platform.srcObject = 'mozSrcObject'
  }

  return platform
})()
<commit_msg>Let platform be a self-invoked function<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

utils.platform = (function () {
  let platform = {}

  const userAgent = (navigator.userAgent).toLowerCase()
  const language = navigator.language || navigator.browserLanguage

  const version = platform.version = (userAgent.match(/.*(?:rv|chrome|webkit|opera|ie)[/: ](.+?)([ );]|$)/) || [])[1]
  const webkitVersion = (userAgent.match(/webkit\/(.+?) /) || [])[1]

  platform.windows = platform.isWindows = !!/windows/.test(userAgent)
  platform.mac = platform.isMac = !!/macintosh/.test(userAgent) || (/mac os x/.test(userAgent) && !/like mac os x/.test(userAgent))
  platform.lion = platform.isLion = !!(/mac os x 10_7/.test(userAgent) && !/like mac os x 10_7/.test(userAgent))
  platform.iPhone = platform.isiPhone = !!/iphone/.test(userAgent)
  platform.iPod = platform.isiPod = !!/ipod/.test(userAgent)
  platform.iPad = platform.isiPad = !!/ipad/.test(userAgent)
  platform.iOS = platform.isiOS = platform.iPhone || platform.iPod || platform.iPad
  platform.android = platform.isAndroid = !!/android/.test(userAgent)
  platform.opera = /opera/.test(userAgent) ? version : 0
  platform.isOpera = !!platform.opera
  platform.msie = /msie/.test(userAgent) && !platform.opera ? version : 0
  platform.isIE = !!platform.msie
  platform.isIE8OrLower = !!(platform.msie && parseInt(platform.msie, 10) <= 8)
  platform.mozilla = /mozilla/.test(userAgent) && !/(compatible|webkit|msie)/.test(userAgent) ? version : 0
  platform.isMozilla = !!platform.mozilla
  platform.webkit = /webkit/.test(userAgent) ? webkitVersion : 0
  platform.isWebkit = !!platform.webkit
  platform.chrome = /chrome/.test(userAgent) ? version : 0
  platform.isChrome = !!platform.chrome
  platform.mobileSafari = /apple.*mobile/.test(userAgent) && platform.iOS ? webkitVersion : 0
  platform.isMobileSafari = !!platform.mobileSafari
  platform.iPadSafari = platform.iPad && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPadSafari = !!platform.iPadSafari
  platform.iPhoneSafari = platform.iPhone && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPhoneSafari = !!platform.iphoneSafari
  platform.iPodSafari = platform.iPod && platform.isMobileSafari ? webkitVersion : 0
  platform.isiPodSafari = !!platform.iPodSafari
  platform.isiOSHomeScreen = platform.isMobileSafari && !/apple.*mobile.*safari/.test(userAgent)
  platform.safari = platform.webkit && !platform.chrome && !platform.iOS && !platform.android ? webkitVersion : 0
  platform.isSafari = !!platform.safari
  platform.language = language.split('-', 1)[0]
  platform.current =
    platform.msie ? 'msie' : platform.mozilla ? 'mozilla' : platform.chrome ? 'chrome' : platform.safari ? 'safari' : platform.opera ? 'opera' : platform.mobileSafari ? 'mobile-safari' : platform.android ? 'android' : 'unknown'

  function platformName (candidates) {
    for (let i = 0; i < candidates.length; i++) {
      if (candidates[i] in window) {
        return 'window.' + candidates[i]
      }
      if (candidates[i] in navigator) {
        return 'navigator.' + candidates[i]
      }
    }
    return undefined
  }

  platform.GUM = platformName(['getUserMedia', 'webkitGetUserMedia', 'mozGetUserMedia', 'msGetUserMedia', 'getGUM'])
  platform.PeerConnection = platformName(['webkitRTCPeerConnection', 'mozRTCPeerConnection', 'msPeerConnection'])
  platform.IceCandidate = platformName(['mozRTCIceCandidate', 'RTCIceCandidate'])
  platform.SessionDescription = platformName(['mozRTCSessionDescription', 'RTCSessionDescription'])
  platform.URL = platformName(['URL', 'webkitURL'])
  platform.AudioContext = platformName(['AudioContext', 'webkitAudioContext'])
  platform.OfflineAudioContext = platformName(['OfflineAudioContext', 'webkitOfflineAudioContext'])
  platform.MediaSource = platformName(['MediaSource', 'WebKitMediaSource'])

  platform.SpeechRecognition = platformName(['SpeechRecognition', 'webkitSpeechRecognition'])
  platform.SpeechGrammarList = platformName(['SpeechGrammarList', 'webkitSpeechGrammarList'])

  /*
   function findWebGLContextName (candidates) {
   var canvas = document.createElement('canvas')
   for (var i = 0; i < candidates.length; i++) {
   var name = candidates[i]
   try {
   if (canvas.getContext(name)) {
   return name
   }
   } catch (e) {}
   }
   return null
   }
   */

  platform.WebGL = 'webgl' // findWebGLContextName(["webgl", "experimental-webgl", "webkit-3d"]);
  platform.WebGL2 = 'webgl2' // findWebGLContextName(["webgl2", "experimental-webgl2"]);

  platform.captureStreamUntilEnded = 'captureStreamUntilEnded'
  if (platform.isMozilla) {
    platform.captureStreamUntilEnded = 'mozCaptureStreamUntilEnded'
  }

  platform.srcObject = 'srcObject'
  if (platform.isMozilla) {
    platform.srcObject = 'mozSrcObject'
  }

  return platform
})()
<|endoftext|>


<commit_before>
// utilities for working with the js-registry site.

exports.publish = publish
exports.tag = tag
exports.adduser = adduser
exports.get = get

var npm = require("../../npm")
  , http = require("http")
  , url = require("url")
  , log = require("./log")
  , uuid = require("./uuid")
  , sha = require("./sha")
  , sys = require("sys")
  , ini = require("./ini")
  , Buffer = require("buffer").Buffer
  , fs = require("fs")
  , path = require("path")
  , Buffer = require('buffer').Buffer
  , fsBinding = process.binding("fs")
function get (project, version, cb) {
  if (!cb) cb = version, version = null
  if (!cb) cb = project, project = null
  if (!cb) throw new Error("No callback provided to registry.get")
  var uri = []
  uri.push(project || "")
  if (version) uri.push(version)
  GET(uri.join("/"), cb)
}

function tag (project, version, tag, cb) { PUT(project+"/"+tag, version, cb) }

function publish (data, cb) {
  // add the dist-url to the data, pointing at the tarball.
  // if the {name} isn't there, then create it.
  // if the {version} is already there, then fail.
  // then:
  // PUT the data to {config.registry}/{data.name}/{data.version}
  try { reg() }
  catch (ex) { return cb(ex) }

  var fullData =
    { _id : data.name
    , name : data.name
    , description : data.description
    , "dist-tags" : {}
    , versions : {}
    , maintainers :
      [ { name : npm.config.get("username")
        , email : npm.config.get("email")
        }
      ]
    }
  fullData.versions[ data.version ] = data
  data._id = data.name+"-"+data.version
  var attURI = encodeURIComponent(data.name)
             + "/-/"
             + encodeURIComponent(data.name)
             + "-"
             + encodeURIComponent(data.version)
             + ".tgz"
  data.dist = { "tarball" : url.resolve(npm.config.get("registry"), attURI) }
  data.dist.tarball = data.dist.tarball.replace(/^https:\/\//, 'http://')

  // first try to just PUT the whole fullData, and this will fail if it's
  // already there, because it'll be lacking a _rev, so couch'll bounce it.
  PUT(encodeURIComponent(data.name), fullData, function (er, parsed, json, response) {
    // get the rev and then upload the attachment
    // a 409 is expected here, if this is a new version of an existing package.
    if (er
        && !(response && response.statusCode === 409)
        && !( parsed
            && parsed.reason === "must supply latest _rev to update existing package"
            )
    ) {
      return log.er(cb, "Failed PUT response "+(response && response.statusCode))(er)
    }
    var sendVersionAgain = !!er
    GET(encodeURIComponent(data.name), function (er, d) {
      if (er) return cb(er)

      var rev = d && d._rev
        , tarball = path.join(npm.cache, data.name, data.version, "package.tgz")
        , dataURI = encodeURIComponent(data.name)+"/"+encodeURIComponent(data.version)
      log(tarball, "tarball")
      attURI += "/" + rev
      upload(attURI, tarball, function (er) {
        if (!sendVersionAgain) return log.er(cb, "Couldn't send tarball")(er)
        PUT(dataURI, data, log.er(cb, "Error sending version data"))
      })
    })
  })
}
function request (method, where, what, cb) {
  log(where, method)
  if ( typeof what === "function" && !cb ) cb = what, what = null
  try { reg() }
  catch (ex) { return cb(ex) }

  var authRequired = what && !where.match(/^\/?adduser\/org\.couchdb\.user:/)
  where = url.resolve(npm.config.get("registry"), where)
  var u = url.parse(where)
    , https = u.protocol === "https:"
    , auth = authRequired && npm.config.get("auth")

  if (authRequired && !auth) {
    log("error for auth")
    return cb(new Error(
      "Cannot insert data into the registry without authorization and https\n"
      + "See: npm-adduser(1)"))
  }
  if (auth && !https) {
    log("Sending authorization over insecure channel.", "WARNING")
  }
  var headers = { "host" : u.host
                , "accept" : "application/json"
                }
  if (auth) headers.authorization = "Basic " + auth
  if (what) {
    if (what instanceof File) {
      log(what.name, "uploading")
      headers["content-type"] = "application/octet-stream"
    } else {
      what = JSON.stringify(what)
      headers["content-type"] = "application/json"
    }
    headers["content-length"] = what.length
  }

  var client = http.createClient(u.port || (https ? 443 : 80), u.hostname, https)
    , request = client.request(method, u.pathname, headers)
  request.addListener("response", function (response) {
    // if (response.statusCode !== 200) return cb(new Error(
    //   "Status code " + response.statusCode + " from PUT "+where))
    var data = ""
    response.addListener("data", function (chunk) { data += chunk })
    response.addListener("end", function () {
      var parsed
      try {
        parsed = JSON.parse(data)
      } catch (ex) {
        ex.message += "\n" + data
        log("error parsing json", "registry")
        return cb(ex, null, data, response)
      }
      log(data.trim(), "registry")
      if (parsed && parsed.error) return cb(new Error(
        parsed.error + (" "+parsed.reason || "")), parsed, data, response)
      cb(null, parsed, data, response)
    })
  })
  if (what instanceof File) {
    var b = new Buffer(1024 * 2)
      , sent = 0
      , i = 0
      , pct = 0
    // FIXME: This timeout hackery is working around an interesting bug
    // in node.  Large request bodies can flood the connection, making
    // things behave in odd ways.  Come back here and remove this when
    // node's http client stops being weird with big messages.
    fsBinding.read(what.fd, b, 0, b.length, null, function W (er, bytesRead) {
      if (er) return log.er(cb, "Failure to read tarball")(er)

      pct = Math.round(sent / what.length * 100 )
      if (!bytesRead || pct > i) {
        log(pct+"%", "uploading")
        i = pct + 7
      }

      sent += bytesRead
      if (!bytesRead) {
        request.end()
        return log("uploaded", "registry")
      }
      request.write(b)
      setTimeout(function () {
        fsBinding.read(what.fd, b, 0, b.length, null, W)
      }, 100)
    })
    return
  } else if (typeof what === "string") {
    // just a json blob
    request.write(what)
  }
  request.end()
}

function GET (where, cb) { request("GET", where, cb) }
function PUT (where, what, cb) { request("PUT", where, what, cb) }

function upload (where, filename, cb) {
  new File(filename, function (er, f) {
    if (er) return log.er(cb, "Couldn't open "+filename)(er)
    PUT(where, f, cb)
  })
}
function File (name, cb) {
  var f = this
  f.name = name
  if (f.loaded) return cb(null, f)
  fs.stat(f.name, function (er, stat) {
    if (er) return log.er(cb, "doesn't exist "+f.name)(er)
    f.length = stat.size
    fs.open(f.name, "r", 0666, function (er, fd) {
      if (er) return log.er(cb, "Error opening "+f.name)(er)
      f.fd = fd
      cb(null, f)
    })
    //
    // fs.readFile(f.name, function (er, data) {
    //   if (er) return log.er(cb, "problem reading "+f.name)(er)
    //   log(name, "read")
    //   f.data = data
    //   cb(null, f)
    // })
  })
}

function reg () {
  var r = npm.config.get("registry")
  if (!r) throw new Error(
    "Must define registry URL before accessing registry.")
  if (r.substr(-1) !== "/") {
    r += "/"
  }
  npm.config.set("registry", r)
  return r
}

function adduser (username, password, email, callback) {
  var salt = uuid.generate()
    , userobj =
      { _id : 'org.couchdb.user:'+username
      , name : username
      , type : "user"
      , roles : []
      , salt : salt
      , password_sha : sha.hex_sha1(password + salt)
      , email : email
      }
  PUT
    ( '/adduser/org.couchdb.user:'+encodeURIComponent(username)
    , userobj
    , function (error, data, json, response) {
        // if the error is a 409, then update the rev.
        if (error || response && response.statusCode !== 201) {
          log(response && response.statusCode, "response")
          log(error, "error")
          return callback(new Error( (response && response.statusCode) + " "+
            "Could not create user "+error+'\n'+JSON.stringify(data)))
        }
        callback()
      }
    )
}
<commit_msg>That log line is atrocious when the reg fetch is big.<commit_after>
// utilities for working with the js-registry site.

exports.publish = publish
exports.tag = tag
exports.adduser = adduser
exports.get = get

var npm = require("../../npm")
  , http = require("http")
  , url = require("url")
  , log = require("./log")
  , uuid = require("./uuid")
  , sha = require("./sha")
  , sys = require("sys")
  , ini = require("./ini")
  , Buffer = require("buffer").Buffer
  , fs = require("fs")
  , path = require("path")
  , Buffer = require('buffer').Buffer
  , fsBinding = process.binding("fs")
function get (project, version, cb) {
  if (!cb) cb = version, version = null
  if (!cb) cb = project, project = null
  if (!cb) throw new Error("No callback provided to registry.get")
  var uri = []
  uri.push(project || "")
  if (version) uri.push(version)
  GET(uri.join("/"), cb)
}

function tag (project, version, tag, cb) { PUT(project+"/"+tag, version, cb) }

function publish (data, cb) {
  // add the dist-url to the data, pointing at the tarball.
  // if the {name} isn't there, then create it.
  // if the {version} is already there, then fail.
  // then:
  // PUT the data to {config.registry}/{data.name}/{data.version}
  try { reg() }
  catch (ex) { return cb(ex) }

  var fullData =
    { _id : data.name
    , name : data.name
    , description : data.description
    , "dist-tags" : {}
    , versions : {}
    , maintainers :
      [ { name : npm.config.get("username")
        , email : npm.config.get("email")
        }
      ]
    }
  fullData.versions[ data.version ] = data
  data._id = data.name+"-"+data.version
  var attURI = encodeURIComponent(data.name)
             + "/-/"
             + encodeURIComponent(data.name)
             + "-"
             + encodeURIComponent(data.version)
             + ".tgz"
  data.dist = { "tarball" : url.resolve(npm.config.get("registry"), attURI) }
  data.dist.tarball = data.dist.tarball.replace(/^https:\/\//, 'http://')

  // first try to just PUT the whole fullData, and this will fail if it's
  // already there, because it'll be lacking a _rev, so couch'll bounce it.
  PUT(encodeURIComponent(data.name), fullData, function (er, parsed, json, response) {
    // get the rev and then upload the attachment
    // a 409 is expected here, if this is a new version of an existing package.
    if (er
        && !(response && response.statusCode === 409)
        && !( parsed
            && parsed.reason === "must supply latest _rev to update existing package"
            )
    ) {
      return log.er(cb, "Failed PUT response "+(response && response.statusCode))(er)
    }
    var sendVersionAgain = !!er
    GET(encodeURIComponent(data.name), function (er, d) {
      if (er) return cb(er)

      var rev = d && d._rev
        , tarball = path.join(npm.cache, data.name, data.version, "package.tgz")
        , dataURI = encodeURIComponent(data.name)+"/"+encodeURIComponent(data.version)
      log(tarball, "tarball")
      attURI += "/" + rev
      upload(attURI, tarball, function (er) {
        if (!sendVersionAgain) return log.er(cb, "Couldn't send tarball")(er)
        PUT(dataURI, data, log.er(cb, "Error sending version data"))
      })
    })
  })
}
function request (method, where, what, cb) {
  log(where, method)
  if ( typeof what === "function" && !cb ) cb = what, what = null
  try { reg() }
  catch (ex) { return cb(ex) }

  var authRequired = what && !where.match(/^\/?adduser\/org\.couchdb\.user:/)
  where = url.resolve(npm.config.get("registry"), where)
  var u = url.parse(where)
    , https = u.protocol === "https:"
    , auth = authRequired && npm.config.get("auth")

  if (authRequired && !auth) {
    log("error for auth")
    return cb(new Error(
      "Cannot insert data into the registry without authorization and https\n"
      + "See: npm-adduser(1)"))
  }
  if (auth && !https) {
    log("Sending authorization over insecure channel.", "WARNING")
  }
  var headers = { "host" : u.host
                , "accept" : "application/json"
                }
  if (auth) headers.authorization = "Basic " + auth
  if (what) {
    if (what instanceof File) {
      log(what.name, "uploading")
      headers["content-type"] = "application/octet-stream"
    } else {
      what = JSON.stringify(what)
      headers["content-type"] = "application/json"
    }
    headers["content-length"] = what.length
  }

  var client = http.createClient(u.port || (https ? 443 : 80), u.hostname, https)
    , request = client.request(method, u.pathname, headers)
  request.addListener("response", function (response) {
    // if (response.statusCode !== 200) return cb(new Error(
    //   "Status code " + response.statusCode + " from PUT "+where))
    var data = ""
    response.addListener("data", function (chunk) { data += chunk })
    response.addListener("end", function () {
      var parsed
      try {
        parsed = JSON.parse(data)
      } catch (ex) {
        ex.message += "\n" + data
        log("error parsing json", "registry")
        return cb(ex, null, data, response)
      }
      if (parsed && parsed.error) return cb(new Error(
        parsed.error + (" "+parsed.reason || "")), parsed, data, response)
      cb(null, parsed, data, response)
    })
  })
  if (what instanceof File) {
    var b = new Buffer(1024 * 2)
      , sent = 0
      , i = 0
      , pct = 0
    // FIXME: This timeout hackery is working around an interesting bug
    // in node.  Large request bodies can flood the connection, making
    // things behave in odd ways.  Come back here and remove this when
    // node's http client stops being weird with big messages.
    fsBinding.read(what.fd, b, 0, b.length, null, function W (er, bytesRead) {
      if (er) return log.er(cb, "Failure to read tarball")(er)

      pct = Math.round(sent / what.length * 100 )
      if (!bytesRead || pct > i) {
        log(pct+"%", "uploading")
        i = pct + 7
      }

      sent += bytesRead
      if (!bytesRead) {
        request.end()
        return log("uploaded", "registry")
      }
      request.write(b)
      setTimeout(function () {
        fsBinding.read(what.fd, b, 0, b.length, null, W)
      }, 100)
    })
    return
  } else if (typeof what === "string") {
    // just a json blob
    request.write(what)
  }
  request.end()
}

function GET (where, cb) { request("GET", where, cb) }
function PUT (where, what, cb) { request("PUT", where, what, cb) }

function upload (where, filename, cb) {
  new File(filename, function (er, f) {
    if (er) return log.er(cb, "Couldn't open "+filename)(er)
    PUT(where, f, cb)
  })
}
function File (name, cb) {
  var f = this
  f.name = name
  if (f.loaded) return cb(null, f)
  fs.stat(f.name, function (er, stat) {
    if (er) return log.er(cb, "doesn't exist "+f.name)(er)
    f.length = stat.size
    fs.open(f.name, "r", 0666, function (er, fd) {
      if (er) return log.er(cb, "Error opening "+f.name)(er)
      f.fd = fd
      cb(null, f)
    })
    //
    // fs.readFile(f.name, function (er, data) {
    //   if (er) return log.er(cb, "problem reading "+f.name)(er)
    //   log(name, "read")
    //   f.data = data
    //   cb(null, f)
    // })
  })
}

function reg () {
  var r = npm.config.get("registry")
  if (!r) throw new Error(
    "Must define registry URL before accessing registry.")
  if (r.substr(-1) !== "/") {
    r += "/"
  }
  npm.config.set("registry", r)
  return r
}

function adduser (username, password, email, callback) {
  var salt = uuid.generate()
    , userobj =
      { _id : 'org.couchdb.user:'+username
      , name : username
      , type : "user"
      , roles : []
      , salt : salt
      , password_sha : sha.hex_sha1(password + salt)
      , email : email
      }
  PUT
    ( '/adduser/org.couchdb.user:'+encodeURIComponent(username)
    , userobj
    , function (error, data, json, response) {
        // if the error is a 409, then update the rev.
        if (error || response && response.statusCode !== 201) {
          log(response && response.statusCode, "response")
          log(error, "error")
          return callback(new Error( (response && response.statusCode) + " "+
            "Could not create user "+error+'\n'+JSON.stringify(data)))
        }
        callback()
      }
    )
}
<|endoftext|>


<commit_before>
import Base64 from '../serializers/base-64'
import TYPES from '../constants/types'

/**
 * Fragment matching regexp for HTML nodes.
 *
 * @type {RegExp}
 */

const FRAGMENT_MATCHER = /data-slate-fragment="([^\s]+)"/

/**
 * Data transfer helper.
 *
 * @type {Transfer}
 */

class Transfer {

  /**
   * Constructor.
   *
   * @param {DataTransfer} data
   */

  constructor(data) {
    this.data = data
    this.cache = {}
  }

  /**
   * Get a data object representing the transfer's primary content type.
   *
   * @return {Object}
   */

  getData() {
    const type = this.getType()
    const data = {}
    data.type = type

    switch (type) {
      case 'files':
        data.files = this.getFiles()
        break
      case 'fragment':
        data.fragment = this.getFragment()
        break
      case 'html':
        data.html = this.getHtml()
        data.text = this.getText()
        break
      case 'node':
        data.node = this.getNode()
        break
      case 'text':
        data.text = this.getText()
        break
    }

    return data
  }

  /**
   * Get the Files content of the data transfer.
   *
   * @return {Array || Void}
   */

  getFiles() {
    if ('files' in this.cache) return this.cache.files

    const { data } = this
    let files

    if (data.items && data.items.length) {
      const fileItems = Array.from(data.items)
        .map(item => item.kind == 'file' ? item.getAsFile() : null)
        .filter(exists => exists)

      if (fileItems.length) files = fileItems
    }

    if (data.files && data.files.length) {
      files = Array.from(data.files)
    }

    this.cache.files = files
    return files
  }

  /**
   * Get the Slate document fragment content of the data transfer.
   *
   * @return {Document || Void}
   */

  getFragment() {
    if ('fragment' in this.cache) return this.cache.fragment

    const html = this.getHtml()
    let encoded = this.data.getData(TYPES.FRAGMENT)
    let fragment

    // If there's html content, and the html includes a `data-fragment`
    // attribute, it's actually a Base64-serialized fragment from a cut/copy.
    if (!encoded && html && ~html.indexOf('<span data-slate-fragment="')) {
      const matches = FRAGMENT_MATCHER.exec(html)
      const [ full, attribute ] = matches
      encoded = attribute
    }

    if (encoded) {
      fragment = Base64.deserializeNode(encoded)
    }

    this.cache.fragment = fragment
    return fragment
  }

  /**
   * Get the HTML content of the data transfer.
   *
   * @return {String || Void}
   */

  getHtml() {
    if ('html' in this.cache) return this.cache.html

    let html
    const string = this.data.getData('text/html')

    if (string != '') html = string

    this.cache.html = html
    return html
  }

  /**
   * Get the Slate node content of the data transfer.
   *
   * @return {Node || Void}
   */

  getNode() {
    if ('node' in this.cache) return this.cache.node

    const encoded = this.data.getData(TYPES.NODE)
    let node

    if (encoded) {
      node = Base64.deserializeNode(encoded)
    }

    this.cache.node = node
    return node
  }

  /**
   * Get the text content of the data transfer.
   *
   * @return {String || Void}
   */

  getText() {
    if ('text' in this.cache) return this.cache.text

    let text
    const string = this.data.getData('text/plain')

    if (string != '') text = string

    this.cache.text = text
    return text
  }

  /**
   * Get the primary type of the data transfer.
   *
   * @return {String}
   */

  getType() {
    if (this.hasFragment()) return 'fragment'
    if (this.hasNode()) return 'node'
    if (this.hasFiles()) return 'files'
    if (this.hasHtml()) return 'html'
    if (this.hasText()) return 'text'
    return 'unknown'
  }

  /**
   * Check whether the data transfer has File content.
   *
   * @return {Boolean}
   */

  hasFiles() {
    return this.getFiles() != null
  }

  /**
   * Check whether the data transfer has HTML content.
   *
   * @return {Boolean}
   */

  hasHtml() {
    return this.getHtml() != null
  }

  /**
   * Check whether the data transfer has text content.
   *
   * @return {Boolean}
   */

  hasText() {
    return this.getText() != null
  }

  /**
   * Check whether the data transfer has a Slate document fragment as content.
   *
   * @return {Boolean}
   */

  hasFragment() {
    return this.getFragment() != null
  }

  /**
   * Check whether the data transfer has a Slate node as content.
   *
   * @return {Boolean}
   */

  hasNode() {
    return this.getFragment() != null
  }

}

/**
 * Export.
 */

export default Transfer
<commit_msg>fix typo in transfer (#247)<commit_after>
import Base64 from '../serializers/base-64'
import TYPES from '../constants/types'

/**
 * Fragment matching regexp for HTML nodes.
 *
 * @type {RegExp}
 */

const FRAGMENT_MATCHER = /data-slate-fragment="([^\s]+)"/

/**
 * Data transfer helper.
 *
 * @type {Transfer}
 */

class Transfer {

  /**
   * Constructor.
   *
   * @param {DataTransfer} data
   */

  constructor(data) {
    this.data = data
    this.cache = {}
  }

  /**
   * Get a data object representing the transfer's primary content type.
   *
   * @return {Object}
   */

  getData() {
    const type = this.getType()
    const data = {}
    data.type = type

    switch (type) {
      case 'files':
        data.files = this.getFiles()
        break
      case 'fragment':
        data.fragment = this.getFragment()
        break
      case 'html':
        data.html = this.getHtml()
        data.text = this.getText()
        break
      case 'node':
        data.node = this.getNode()
        break
      case 'text':
        data.text = this.getText()
        break
    }

    return data
  }

  /**
   * Get the Files content of the data transfer.
   *
   * @return {Array || Void}
   */

  getFiles() {
    if ('files' in this.cache) return this.cache.files

    const { data } = this
    let files

    if (data.items && data.items.length) {
      const fileItems = Array.from(data.items)
        .map(item => item.kind == 'file' ? item.getAsFile() : null)
        .filter(exists => exists)

      if (fileItems.length) files = fileItems
    }

    if (data.files && data.files.length) {
      files = Array.from(data.files)
    }

    this.cache.files = files
    return files
  }

  /**
   * Get the Slate document fragment content of the data transfer.
   *
   * @return {Document || Void}
   */

  getFragment() {
    if ('fragment' in this.cache) return this.cache.fragment

    const html = this.getHtml()
    let encoded = this.data.getData(TYPES.FRAGMENT)
    let fragment

    // If there's html content, and the html includes a `data-fragment`
    // attribute, it's actually a Base64-serialized fragment from a cut/copy.
    if (!encoded && html && ~html.indexOf('<span data-slate-fragment="')) {
      const matches = FRAGMENT_MATCHER.exec(html)
      const [ full, attribute ] = matches
      encoded = attribute
    }

    if (encoded) {
      fragment = Base64.deserializeNode(encoded)
    }

    this.cache.fragment = fragment
    return fragment
  }

  /**
   * Get the HTML content of the data transfer.
   *
   * @return {String || Void}
   */

  getHtml() {
    if ('html' in this.cache) return this.cache.html

    let html
    const string = this.data.getData('text/html')

    if (string != '') html = string

    this.cache.html = html
    return html
  }

  /**
   * Get the Slate node content of the data transfer.
   *
   * @return {Node || Void}
   */

  getNode() {
    if ('node' in this.cache) return this.cache.node

    const encoded = this.data.getData(TYPES.NODE)
    let node

    if (encoded) {
      node = Base64.deserializeNode(encoded)
    }

    this.cache.node = node
    return node
  }

  /**
   * Get the text content of the data transfer.
   *
   * @return {String || Void}
   */

  getText() {
    if ('text' in this.cache) return this.cache.text

    let text
    const string = this.data.getData('text/plain')

    if (string != '') text = string

    this.cache.text = text
    return text
  }

  /**
   * Get the primary type of the data transfer.
   *
   * @return {String}
   */

  getType() {
    if (this.hasFragment()) return 'fragment'
    if (this.hasNode()) return 'node'
    if (this.hasFiles()) return 'files'
    if (this.hasHtml()) return 'html'
    if (this.hasText()) return 'text'
    return 'unknown'
  }

  /**
   * Check whether the data transfer has File content.
   *
   * @return {Boolean}
   */

  hasFiles() {
    return this.getFiles() != null
  }

  /**
   * Check whether the data transfer has HTML content.
   *
   * @return {Boolean}
   */

  hasHtml() {
    return this.getHtml() != null
  }

  /**
   * Check whether the data transfer has text content.
   *
   * @return {Boolean}
   */

  hasText() {
    return this.getText() != null
  }

  /**
   * Check whether the data transfer has a Slate document fragment as content.
   *
   * @return {Boolean}
   */

  hasFragment() {
    return this.getFragment() != null
  }

  /**
   * Check whether the data transfer has a Slate node as content.
   *
   * @return {Boolean}
   */

  hasNode() {
    return this.getNode() != null
  }

}

/**
 * Export.
 */

export default Transfer
<|endoftext|>


<commit_before>/** @babel */
/** @jsx etch.dom */

import { CompositeDisposable } from 'atom';
import etch from 'etch';
import changeCase from 'change-case';
import path from 'path';
import { EDIT_URI } from './view-uri';
import manager from '../Manager';
import Project from '../models/Project';

const disposables = new CompositeDisposable();

etch.setScheduler(atom.views);

export default class EditView {
  constructor(props, children) {
    this.props = props;
    this.children = children;
    etch.initialize(this);

    this.storeFocusedElement();

    this.setFocus();

    this.element.addEventListener('click', (event) => {
      if (event.target === this.refs.save) {
        this.saveProject();
      }
    });

    disposables.add(atom.commands.add(this.element, {
      'core:save': () => this.saveProject(),
      'core:confirm': () => this.saveProject(),
    }));

    disposables.add(atom.commands.add('atom-workspace', {
      'core:cancel': () => this.close(),
    }));
  }

  getFocusElement() {
    return this.refs.title;
  }

  setFocus() {
    const focusElement = this.getFocusElement();

    if (focusElement) {
      setTimeout(() => {
        focusElement.focus();
      }, 0);
    }
  }

  storeFocusedElement() {
    this.previouslyFocusedElement = document.activeElement;
  }

  restoreFocus() {
    if (this.previouslyFocusedElement) {
      this.previouslyFocusedElement.focus();
    }
  }

  close() {
    this.destroy();
  }

  async destroy() {
    const pane = atom.workspace.paneForURI(EDIT_URI);
    if (pane) {
      const item = pane.itemForURI(EDIT_URI);
      pane.destroyItem(item);
    }

    disposables.dispose();
    await etch.destroy(this);
  }

  saveProject() {
    const projectProps = {
      title: this.refs.title.value,
      paths: atom.project.getPaths(),
      group: this.refs.group.value,
      icon: this.refs.icon.value,
      devMode: this.refs.devMode.checked,
    };
    let message = `${projectProps.title} has been saved.`;

    if (this.props.project) {
      // Paths should already be up-to-date, so use
      // the current paths as to not break possible relative paths.
      projectProps.paths = this.props.project.getProps().paths;
    }

    // many stuff will break if there is no root path,
    // so we don't continue without a root path
    if(!projectProps.paths.length){
      atom.notifications.addError(`You must have at least one folder in your project before you can save !`);
    } else {
      manager.saveProject(projectProps);

      if (this.props.project) {
        message = `${this.props.project.title} has been updated.`;
      }
      atom.notifications.addSuccess(message);

      this.close();
    }
  }

  update(props, children) {
    this.props = props;
    this.children = children;
  }

  getTitle() {
    if (this.props.project) {
      return `Edit ${this.props.project.title}`;
    }

    return 'Save Project';
  }

  getIconName() { // eslint-disable-line class-methods-use-this
    return 'gear';
  }

  getURI() { // eslint-disable-line class-methods-use-this
    return EDIT_URI;
  }

  render() {
    const defaultProps = Project.defaultProps;
    const rootPath = atom.project.getPaths()[0];
    let props = defaultProps;

    if (atom.config.get('project-manager.prettifyTitle')) {
      props.title = changeCase.titleCase(path.basename(rootPath));
    }

    if (this.props.project && this.props.project.source === 'file') {
      const projectProps = this.props.project.getProps();
      props = Object.assign({}, props, projectProps);
    }

    const wrapperStyle = {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
    };

    const style = {
      width: '500px',
    };

    return (

{this.getTitle()}

            Title
            <input ref="title" type="text" className="input-text" value={props.title} tabIndex="0" />

            Group
            <input ref="group" type="text" className="input-text" value={props.group} tabIndex="1" />

            Icon
            <input ref="icon" type="text" className="input-text" value={props.icon} tabIndex="2" />

            Development mode
              <input
                ref="devMode"
                id="devMode"
                name="devMode"
                type="checkbox"
                className="input-toggle"
                checked={props.devMode}
                tabIndex="3"
              />

            <button ref="save" className="btn btn-primary" tabIndex="4">Save</button>

    );
  }
}
<commit_msg>lint stuff<commit_after>/** @babel */
/** @jsx etch.dom */

import { CompositeDisposable } from 'atom';
import etch from 'etch';
import changeCase from 'change-case';
import path from 'path';
import { EDIT_URI } from './view-uri';
import manager from '../Manager';
import Project from '../models/Project';

const disposables = new CompositeDisposable();

etch.setScheduler(atom.views);

export default class EditView {
  constructor(props, children) {
    this.props = props;
    this.children = children;
    etch.initialize(this);

    this.storeFocusedElement();

    this.setFocus();

    this.element.addEventListener('click', (event) => {
      if (event.target === this.refs.save) {
        this.saveProject();
      }
    });

    disposables.add(atom.commands.add(this.element, {
      'core:save': () => this.saveProject(),
      'core:confirm': () => this.saveProject(),
    }));

    disposables.add(atom.commands.add('atom-workspace', {
      'core:cancel': () => this.close(),
    }));
  }

  getFocusElement() {
    return this.refs.title;
  }

  setFocus() {
    const focusElement = this.getFocusElement();

    if (focusElement) {
      setTimeout(() => {
        focusElement.focus();
      }, 0);
    }
  }

  storeFocusedElement() {
    this.previouslyFocusedElement = document.activeElement;
  }

  restoreFocus() {
    if (this.previouslyFocusedElement) {
      this.previouslyFocusedElement.focus();
    }
  }

  close() {
    this.destroy();
  }

  async destroy() {
    const pane = atom.workspace.paneForURI(EDIT_URI);
    if (pane) {
      const item = pane.itemForURI(EDIT_URI);
      pane.destroyItem(item);
    }

    disposables.dispose();
    await etch.destroy(this);
  }

  saveProject() {
    const projectProps = {
      title: this.refs.title.value,
      paths: atom.project.getPaths(),
      group: this.refs.group.value,
      icon: this.refs.icon.value,
      devMode: this.refs.devMode.checked,
    };
    let message = `${projectProps.title} has been saved.`;

    if (this.props.project) {
      // Paths should already be up-to-date, so use
      // the current paths as to not break possible relative paths.
      projectProps.paths = this.props.project.getProps().paths;
    }

    // many stuff will break if there is no root path,
    // so we don't continue without a root path
    if (!projectProps.paths.length) {
      atom.notifications.addError('You must have at least one folder in your project before you can save !');
    } else {
      manager.saveProject(projectProps);

      if (this.props.project) {
        message = `${this.props.project.title} has been updated.`;
      }
      atom.notifications.addSuccess(message);

      this.close();
    }
  }

  update(props, children) {
    this.props = props;
    this.children = children;
  }

  getTitle() {
    if (this.props.project) {
      return `Edit ${this.props.project.title}`;
    }

    return 'Save Project';
  }

  getIconName() { // eslint-disable-line class-methods-use-this
    return 'gear';
  }

  getURI() { // eslint-disable-line class-methods-use-this
    return EDIT_URI;
  }

  render() {
    const defaultProps = Project.defaultProps;
    const rootPath = atom.project.getPaths()[0];
    let props = defaultProps;

    if (atom.config.get('project-manager.prettifyTitle')) {
      props.title = changeCase.titleCase(path.basename(rootPath));
    }

    if (this.props.project && this.props.project.source === 'file') {
      const projectProps = this.props.project.getProps();
      props = Object.assign({}, props, projectProps);
    }

    const wrapperStyle = {
      display: 'flex',
      alignItems: 'center',
      justifyContent: 'center',
    };

    const style = {
      width: '500px',
    };

    return (

{this.getTitle()}

            Title
            <input ref="title" type="text" className="input-text" value={props.title} tabIndex="0" />

            Group
            <input ref="group" type="text" className="input-text" value={props.group} tabIndex="1" />

            Icon
            <input ref="icon" type="text" className="input-text" value={props.icon} tabIndex="2" />

            Development mode
              <input
                ref="devMode"
                id="devMode"
                name="devMode"
                type="checkbox"
                className="input-toggle"
                checked={props.devMode}
                tabIndex="3"
              />

            <button ref="save" className="btn btn-primary" tabIndex="4">Save</button>

    );
  }
}
<|endoftext|>


<commit_before>var Promise = require('bluebird')
  , github = require('../github')
  , linter = require('eslint').linter;

module.exports = {
  repo: {
    user: null,
    name: null
  },

  pr: {
    action: null,
    number: null,
    sha: null
  },

  cfg: null,

  process: function(job, done) {
    // Set data about the pull request
    this.setData(job.data);

    // Check if PR is still open
    this.isOpen()
      .bind(this)
      .then(function() {
        // Get .eslintrc
        return this.getFileContents('.eslintrc', true);
      })
      .then(function(eslintCfg) {
        // Store config
        this.cfg = eslintCfg;

        // Get changed files
        return this.getChangedFiles();
      })
      .then(function(changedFiles) {
        return this.validateFiles(changedFiles);
      })
      .then(function(messages) {
        console.log('ESLINT: ', messages);
        return this.processMessages(messages);
      })
      .then(function() {
        console.log('all done!');
      })
      .catch(function(err) {
        console.error('error', err);
      })
      .finally(function() {
        this.reset();
        done();
      });
  },

  setData: function(data) {
    this.repo.user = data.repository.owner.login;
    this.repo.name = data.repository.name;
    this.pr.action = data.action;
    this.pr.number = data.number;
    this.pr.sha = data.pull_request.head.sha;
  },

  isOpen: function() {
    var that = this;

    return new Promise(function(resolve, reject) {
      github.pullRequests.get({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number
      }, function(err, res) {
        if (!err && !res.merged) return resolve();

        return reject(err);
      });
    });
  },

  getChangedFiles: function() {
    var that = this
    // TODO: handle pagination
    return new Promise(function(resolve, reject) {
      github.pullRequests.getFiles({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number,
        per_page: 100
      }, function(err, res) {
        if (!err) return resolve(res);

        return reject(err);
      });
    });
  },

  getFileContents: function(path, parseJson, ref) {
    var that = this
      , params = {
          user: this.repo.user,
          repo: this.repo.name,
          path: path
        };

    // Set ref if specified
    if (ref) params.ref = ref;

    return new Promise(function(resolve, reject) {
      github.repos.getContent(params, function(err, res) {
        if (!err) {
          var content = new Buffer(res.content, 'base64').toString('utf8');

          if (parseJson) {
            content = JSON.parse(content);
          }

          return resolve(content);
        }

        return reject(err);
      });
    });
  },

  validateFiles: function(files) {
    var that = this
      , result = { };

    var promise = new Promise(function(resolve, reject) {
      files.forEach(function(file, index) {
        console.info('processing file', file.filename);
        var filename = file.filename
          , ref = that.pr.sha;

        // If ref not found, skip
        if (!ref) return;

        that.getFileContents(filename, false, ref)
          .then(function(contents) {
            return that.eslint(contents);
          })
          .then(function(messages) {
            result[filename] = messages;

            // TODO: this is a bit weird, refactor
            if (files.length === (index + 1)) {
              return resolve(result);
            }
          })
          .catch(function(err, foo) {
            return reject(err);
          });
      });
    });

    return promise;
  },

  eslint: function(contents) {
    var that = this;

    return new Promise(function(resolve, reject) {
      var messages = linter.verify(contents, that.cfg);

      return resolve(messages);
    });
  },

  processMessages: function(messages) {
    var that = this
      , comments = [];

    Object.keys(messages).forEach(function(filename) {
      messages[filename].forEach(function(msg) {
        comments.push(that.createComment(msg.message, filename, msg.line));
      });
    });

    return Promise.all(comments);
  },

  createComment: function(body, path, position) {
    var that = this;

    return new Promise(function(resolve, reject) {
      console.log('creating comment', body, path, position);
      github.pullRequests.createComment({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number,
        commit_id: that.pr.sha,
        body: body,
        path: path,
        position: position
      }, function(err) {
        if (!err) return resolve();

        return reject();
      });

      resolve();
    });
  },

  reset: function() {
    this.repo.user = null;
    this.repo.name = null;
    this.pr.action = null;
    this.pr.number = null;
    this.pr.sha = null;
    this.cfg = null;
  }
};<commit_msg>Minor tweak<commit_after>var Promise = require('bluebird')
  , github = require('../github')
  , linter = require('eslint').linter;

module.exports = {
  repo: {
    user: null,
    name: null
  },

  pr: {
    action: null,
    number: null,
    sha: null
  },

  cfg: null,

  process: function(job, done) {
    // Set data about the pull request
    this.setData(job.data);

    // Check if PR is still open
    this.isOpen()
      .bind(this)
      .then(function() {
        // Get .eslintrc
        return this.getFileContents('.eslintrc', true);
      })
      .then(function(eslintCfg) {
        // Store config
        this.cfg = eslintCfg;

        // Get changed files
        return this.getChangedFiles();
      })
      .then(function(changedFiles) {
        return this.validateFiles(changedFiles);
      })
      .then(function(messages) {
        console.log('ESLINT: ', messages);
        return this.processMessages(messages);
      })
      .then(function() {
        console.log('all done!');
      })
      .catch(function(err) {
        console.error('error', err);
      })
      .finally(function() {
        this.reset();
        done();
      });
  },

  setData: function(data) {
    this.repo.user = data.repository.owner.login;
    this.repo.name = data.repository.name;
    this.pr.action = data.action;
    this.pr.number = data.number;
    this.pr.sha = data.pull_request.head.sha;
  },

  isOpen: function() {
    var that = this;

    return new Promise(function(resolve, reject) {
      github.pullRequests.get({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number
      }, function(err, res) {
        if (!err && !res.merged) return resolve();

        return reject(err);
      });
    });
  },

  getChangedFiles: function() {
    var that = this
    // TODO: handle pagination
    return new Promise(function(resolve, reject) {
      github.pullRequests.getFiles({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number,
        per_page: 100
      }, function(err, res) {
        if (!err) return resolve(res);

        return reject(err);
      });
    });
  },

  getFileContents: function(path, parseJson, ref) {
    var that = this
      , params = {
          user: this.repo.user,
          repo: this.repo.name,
          path: path
        };

    // Set ref if specified
    if (ref) params.ref = ref;

    return new Promise(function(resolve, reject) {
      github.repos.getContent(params, function(err, res) {
        if (!err) {
          var content = new Buffer(res.content, 'base64').toString('utf8');

          if (parseJson) {
            content = JSON.parse(content);
          }

          return resolve(content);
        }

        return reject(err);
      });
    });
  },

  validateFiles: function(files) {
    var that = this
      , result = { };

    var promise = new Promise(function(resolve, reject) {
      files.forEach(function(file, index) {
        console.info('processing file', file.filename);
        var filename = file.filename
          , ref = that.pr.sha;

        // If ref not found, skip
        if (!ref) return;

        that.getFileContents(filename, false, ref)
          .then(function(contents) {
            return that.eslint(contents);
          })
          .then(function(messages) {
            result[filename] = messages;

            // TODO: this is a bit weird, refactor
            if (files.length === (index + 1)) {
              return resolve(result);
            }
          })
          .catch(function(err, foo) {
            return reject(err);
          });
      });
    });

    return promise;
  },

  eslint: function(contents) {
    var that = this;

    return new Promise(function(resolve, reject) {
      var messages = linter.verify(contents, that.cfg);

      return resolve(messages);
    });
  },

  processMessages: function(messages) {
    var that = this
      , comments = [];

    Object.keys(messages).forEach(function(filename) {
      messages[filename].forEach(function(msg) {
        comments.push(that.createComment(msg.message, filename, msg.line));
      });
    });

    return Promise.all(comments);
  },

  createComment: function(body, path, position) {
    var that = this;

    return new Promise(function(resolve, reject) {
      github.pullRequests.createComment({
        user: that.repo.user,
        repo: that.repo.name,
        number: that.pr.number,
        commit_id: that.pr.sha,
        body: body,
        path: path,
        position: position
      }, function(err) {
        if (!err) {
          console.log('created comment', body, path, position);
          return resolve();
        }

        return reject();
      });

      resolve();
    });
  },

  reset: function() {
    this.repo.user = null;
    this.repo.name = null;
    this.pr.action = null;
    this.pr.number = null;
    this.pr.sha = null;
    this.cfg = null;
  }
};<|endoftext|>


<commit_before>const baseConfig = require('./webpack.base.conf');
const webpack = require('webpack');
const merge = require('webpack-merge');
const utils = require('./utils');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const webpackProdConfig = merge(baseConfig, {
    mode: 'production',
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
    },
    devtool: '#source-map',
    optimization: {
        splitChunks: {
            name: 'commons',
            chunks: 'all',
        },
    },
    plugins: [
        new WebpackCleanupPlugin(),
        new webpack.EnvironmentPlugin({
            NODE_ENV: 'production',
            DEBUG: false,
        }),

        new HtmlWebpackPlugin({
            template: require('html-webpack-template'),
            filename: path.resolve(__dirname, '../dist/index.html'),
            title: 'React-Typescript-Gen',
            appMountId: 'root',
            inject: false,
            hash: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true,
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency',
        }),
        new webpack.HashedModuleIdsPlugin(),
        // copy custom static assets
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: 'dist/assets',
                ignore: ['.*'],
            },
        ]),
    ],
});

module.exports = webpackProdConfig;
<commit_msg>fix: build for moving static assets<commit_after>const baseConfig = require('./webpack.base.conf');
const webpack = require('webpack');
const merge = require('webpack-merge');
const utils = require('./utils');
const path = require('path');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const WebpackCleanupPlugin = require('webpack-cleanup-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');

const webpackProdConfig = merge(baseConfig, {
    mode: 'production',
    output: {
        path: path.resolve(__dirname, '../dist'),
        filename: utils.assetsPath('js/[name].[chunkhash].js'),
        chunkFilename: utils.assetsPath('js/[id].[chunkhash].js'),
    },
    devtool: '#source-map',
    optimization: {
        splitChunks: {
            name: 'commons',
            chunks: 'all',
        },
    },
    plugins: [
        new WebpackCleanupPlugin(),
        new webpack.EnvironmentPlugin({
            NODE_ENV: 'production',
            DEBUG: false,
        }),

        new HtmlWebpackPlugin({
            template: require('html-webpack-template'),
            filename: path.resolve(__dirname, '../dist/index.html'),
            title: 'React-Typescript-Gen',
            appMountId: 'root',
            inject: false,
            hash: true,
            minify: {
                removeComments: true,
                collapseWhitespace: true,
                removeAttributeQuotes: true,
                // more options:
                // https://github.com/kangax/html-minifier#options-quick-reference
            },
            // necessary to consistently work with multiple chunks via CommonsChunkPlugin
            chunksSortMode: 'dependency',
        }),
        new webpack.HashedModuleIdsPlugin(),
        // copy custom static assets
        new CopyWebpackPlugin([
            {
                from: path.resolve(__dirname, '../static'),
                to: 'static',
                ignore: ['.*'],
            },
        ]),
    ],
});

module.exports = webpackProdConfig;
<|endoftext|>


<commit_before>"use strict";

const exec = require("../exec.js");

module.exports = (config) => {
    return _run(config);
};

function _run(config) {
    let promise = new Promise((resolve) => {
        resolve();
    });

    if (config.commands.local.length > 0) {
        for (var i = 0; i < config.commands.local.length; i++) {
            promise = promise.then(exec.local.bind(
                    exec,
                    config.internal.write,
                    config.commands.local[i],
                    {
                        cwd: config.workspace,
                    }
                )
            );
        }
    }

    promise = promise.then(() => {
        return config;
    });

    return promise;
}<commit_msg>[WIP] add Promise to run many commands in same time<commit_after>"use strict";

const exec = require("../exec.js");

module.exports = (config) => {
    return _run(config);
};

function _run(config) {
    let promise = new Promise((resolve) => {
        resolve();
    });

    if (config.commands.local.length > 0) {
        for (let i = 0; i < config.commands.local.length; i++) {
            if (Array.isArray(config.commands.local[i])) {

                promise = promise.then(() => {
                    let promises = [];

                    for (let j = 0; j < config.commands.local[i].length; j++) {
                        promises.push(
                            exec.local(
                                config.internal.write,
                                config.commands.local[i][j],
                                {
                                    cwd: config.workspace,
                                }
                            )
                        );
                    }

                    return Promise.all(promises);
                });
            } else {
                promise = promise.then(exec.local.bind(
                        exec,
                        config.internal.write,
                        config.commands.local[i],
                        {
                            cwd: config.workspace,
                        }
                    )
                );
            }
        }
    }

    promise = promise.then(() => {
        return config;
    });

    return promise;
}<|endoftext|>