<commit_before>/**
 * @since 2016-10-22 13:12
 * @author vivaxy
 */

import fs from 'fs';
import path from 'path';
import fse from 'fs-extra';

const remove = async(file) => {
    const result = await new Promise(((resolve) => {
        fse.remove(file, (err) => {
            if (err) {
                throw err;
            }
            resolve();
        });
    }));
    console.log(`Removed ${file}`);
    return result;
};

const read = async(file) => {
    return await new Promise((resolve) => {
        fs.readFile(file, 'utf8', (err, data) => {
                if (err) {
                    throw err;
                }
                resolve(data);
            }
        );
    });
};

const write = async(file, data) => {
    const result = new Promise((resolve) => {
        fse.outputFile(file, data, (err) => {
            if (err) {
                throw err;
            }
            resolve();
        });
    });
    console.log(`Write to ${file}`);
    return result;
};

const createPackageJSON = async() => {
    const filename = `./package.json`;
    const data = await read(filename);
    const packageData = JSON.parse(data);
    const {
        name,
        version,
        description,
        main,
        scripts,
        repository,
        keywords,
        author,
        license,
        bugs,
        homepage,
        dependencies,
        devDependencies,
        peerDependencies,
    } = packageData;

    Reflect.deleteProperty(scripts, `setup`);
    Reflect.deleteProperty(devDependencies, `babel-cli`);
    Reflect.deleteProperty(devDependencies, `fs-extra`);

    const outputPackage = {
        name: path.resolve(__dirname, 'script'),
        version: `0.0.0`,
        reactScaffoldVersion: version,
        description: `project from ${description}`,
        main,
        scripts: scripts,
        repository: {
            ...repository,
            url: ``,
        },
        keywords,
        author,
        license,
        bugs: {
            ...bugs,
            url: ``,
        },
        homepage: ``,
        dependencies,
        devDependencies,
        peerDependencies,
    };

    return await write(filename, JSON.stringify(outputPackage, null, 2));
};

const createREADME = async() => {
    const filename = `./README.md`;
    const data = await read(filename);
    const partsToRemove = [
        `INITIALIZE`,
        `CONTRIBUTE`,
        `TODO`,
    ];
    let data_removed = data;
    partsToRemove.forEach((part) => {
        data_removed = data_removed.replace(new RegExp(`## ${part}.+?##`), `\n##`);
    });
    return await write(filename, data_removed);
};

const createCHANGELOG = async() => {
    const filename = `./CHANGELOG.md`;
    return await write(filename, `# 0.0.0\n`);
};

/**
 - remove git info `rm -rf .git`
 - update config in files
    - package.json
        - name
        - version
        - repository
            - url
        - bugs
            - url
        - homepage
        - scripts
            - setup
    - webpack.config.js
        - DEVELOPMENT_PORT
    - README.md
        - INITIALIZE
        - CONTRIBUTE
        - TODO
        - CHANGELOG.md
    - .gitignore
 - remove scripts
 */
const setup = async() => {
    await remove(`.git`);
    await createPackageJSON();
    await createREADME();
    await createCHANGELOG();
    await remove(`scripts`);
};

setup();
<commit_msg>fix readme<commit_after>/**
 * @since 2016-10-22 13:12
 * @author vivaxy
 */

import fs from 'fs';
import path from 'path';
import fse from 'fs-extra';

const remove = async(file) => {
    const result = await new Promise(((resolve) => {
        fse.remove(file, (err) => {
            if (err) {
                throw err;
            }
            resolve();
        });
    }));
    console.log(`Removed ${file}`);
    return result;
};

const read = async(file) => {
    return await new Promise((resolve) => {
        fs.readFile(file, 'utf8', (err, data) => {
                if (err) {
                    throw err;
                }
                resolve(data);
            }
        );
    });
};

const write = async(file, data) => {
    const result = new Promise((resolve) => {
        fse.outputFile(file, data, (err) => {
            if (err) {
                throw err;
            }
            resolve();
        });
    });
    console.log(`Write to ${file}`);
    return result;
};

const createPackageJSON = async() => {
    const filename = `./package.json`;
    const data = await read(filename);
    const packageData = JSON.parse(data);
    const {
        name,
        version,
        description,
        main,
        scripts,
        repository,
        keywords,
        author,
        license,
        bugs,
        homepage,
        dependencies,
        devDependencies,
        peerDependencies,
    } = packageData;

    Reflect.deleteProperty(scripts, `setup`);
    Reflect.deleteProperty(devDependencies, `babel-cli`);
    Reflect.deleteProperty(devDependencies, `fs-extra`);

    const outputPackage = {
        name: path.resolve(__dirname, 'script'),
        version: `0.0.0`,
        reactScaffoldVersion: version,
        description: `project from ${description}`,
        main,
        scripts: scripts,
        repository: {
            ...repository,
            url: ``,
        },
        keywords,
        author,
        license,
        bugs: {
            ...bugs,
            url: ``,
        },
        homepage: ``,
        dependencies,
        devDependencies,
        peerDependencies,
    };

    return await write(filename, JSON.stringify(outputPackage, null, 2));
};

const createREADME = async() => {
    const filename = `./README.md`;
    const data = await read(filename);
    const partsToRemove = [
        `INITIALIZE`,
        `CONTRIBUTE`,
        `TODO`,
    ];
    let data_removed = data;
    partsToRemove.forEach((part) => {
        data_removed = data_removed.replace(new RegExp(`## ${part}[\\s\\S]+?##`), `##`);
    });
    return await write(filename, data_removed);
};

const createCHANGELOG = async() => {
    const filename = `./CHANGELOG.md`;
    return await write(filename, `# 0.0.0\n`);
};

/**
 - remove git info `rm -rf .git`
 - update config in files
    - package.json
        - name
        - version
        - repository
            - url
        - bugs
            - url
        - homepage
        - scripts
            - setup
    - webpack.config.js
        - DEVELOPMENT_PORT
    - README.md
        - INITIALIZE
        - CONTRIBUTE
        - TODO
        - CHANGELOG.md
    - .gitignore
 - remove scripts
 */
const setup = async() => {
    await remove(`.git`);
    await createPackageJSON();
    await createREADME();
    await createCHANGELOG();
    await remove(`scripts`);
};

setup();
<|endoftext|>


<commit_before>import tokens from '@/tokens/tokens-poa.json';
import contracts from '@/contracts/contract-abi-poa.json';
import poa from '@/assets/images/networks/poa.svg';
// import { EthAbi } from '../ensAbis';

export default {
  name: 'POA',
  name_long: 'Proof of Authority',
  homePage: 'https://poa.network/',
  blockExplorerTX: 'https://poaexplorer.com/tx/[[txHash]]',
  blockExplorerAddr: 'https://poaexplorer.com/address/[[address]]',
  chainID: 99,
  tokens: tokens,
  contracts: contracts,
  ensResolver: '',
  ensAbi: '',
  icon: poa
};
<commit_msg>Update POA explorer<commit_after>import tokens from '@/tokens/tokens-poa.json';
import contracts from '@/contracts/contract-abi-poa.json';
import poa from '@/assets/images/networks/poa.svg';
// import { EthAbi } from '../ensAbis';

export default {
  name: 'POA',
  name_long: 'Proof of Authority',
  homePage: 'https://poa.network/',
  blockExplorerTX: 'https://blockscout.com/poa/core/tx/[[txHash]]',
  blockExplorerAddr: 'https://blockscout.com/poa/core/address/[[address]]',
  chainID: 99,
  tokens: tokens,
  contracts: contracts,
  ensResolver: '',
  ensAbi: '',
  icon: poa
};
<|endoftext|>


<commit_before>/**
 * npm run watch - script to regen app and service-worker.
 * TODO browserify/watchify only listens to app js. More?
 */

var fs = require('fs'),
	path = require('path'),
	browserify = require('browserify'),
	watchify = require('watchify'),
	babelify = require('babelify'),
	swPrecache = require('sw-precache');

// Disable sourcemaps for now, etc.
// var isDebugMode = process.env.NODE_ENV === 'development';
var isDebugMode = false;

var b = browserify({
		entries: [path.join('javascripts', 'dicey.js')],
		// sourcemaps
		debug: isDebugMode,
		cache: {},
		packageCache: {},
		plugin: [watchify]
	})
	.on('update', bundle);

function formatTimestamp(d) {
	return '[' + d.toLocaleString() + ']';
}

function log(msg) {
	console.log(formatTimestamp(new Date()), msg);
}

function bundle() {

	var start = Date.now();
	log('watch.js: bundle task running...');

	generateBundle().on('finish', () => {

		generateServiceWorker().then(() => {
			log('watch.js: complete in ' + ((Date.now() - start) / 1000) + 's');
			log('---');
		}).catch(function (err) {
			log('ERROR generating service-worker!');
		});

	});

}

/**
 * Rebuild ReactJS app and package for client browser.
 * @return {stream.Writable} https://nodejs.org/api/stream.html#stream_class_stream_writable
 */
function generateBundle() {
	log('generateBundle...');
	return b
	.transform('babelify', {presets: ['react']})
	.bundle()
	.on('error', (err) => {
		log(err.message);
		this.emit('end');
	})
	.pipe(fs.createWriteStream(path.join('public', 'bundle.js')))
	.on('finish', () => {
		log('generateBundle done.');
	});
}

/**
 * @return {Promise} Promise when finished.
 */
function generateServiceWorker() {
	log('generateServiceWorker...');
	return swPrecache.write(path.join('public', 'service-worker.js'), {
		staticFileGlobs: ['public' + '/**/*.{js,html,css,png,jpg,gif}'],
		stripPrefix: 'public'
	}).then(function () {
		log('generateServiceWorker done.');
	});
}

// Kick things off to start.
bundle();
<commit_msg>Add firebase.js to bundle.js.<commit_after>/**
 * npm run watch - script to regen app and service-worker.
 * TODO browserify/watchify only listens to app js. More?
 */

var fs = require('fs'),
	path = require('path'),
	browserify = require('browserify'),
	watchify = require('watchify'),
	babelify = require('babelify'),
	swPrecache = require('sw-precache');

// Disable sourcemaps for now, etc.
// var isDebugMode = process.env.NODE_ENV === 'development';
var isDebugMode = false;

var b = browserify({
		entries: [
			path.join('javascripts', 'dicey.js'),
			path.join('javascripts', 'firebase.js')
		],
		// sourcemaps
		debug: isDebugMode,
		cache: {},
		packageCache: {},
		plugin: [watchify]
	})
	.on('update', bundle);

function formatTimestamp(d) {
	return '[' + d.toLocaleString() + ']';
}

function log(msg) {
	console.log(formatTimestamp(new Date()), msg);
}

function bundle() {

	var start = Date.now();
	log('watch.js: bundle task running...');

	generateBundle().on('finish', () => {

		generateServiceWorker().then(() => {
			log('watch.js: complete in ' + ((Date.now() - start) / 1000) + 's');
			log('---');
		}).catch(function (err) {
			log('ERROR generating service-worker!');
		});

	});

}

/**
 * Rebuild ReactJS app and package for client browser.
 * @return {stream.Writable} https://nodejs.org/api/stream.html#stream_class_stream_writable
 */
function generateBundle() {
	log('generateBundle...');
	return b
	.transform('babelify', {presets: ['react']})
	.bundle()
	.on('error', (err) => {
		log(err.message);
		this.emit('end');
	})
	.pipe(fs.createWriteStream(path.join('public', 'bundle.js')))
	.on('finish', () => {
		log('generateBundle done.');
	});
}

/**
 * @return {Promise} Promise when finished.
 */
function generateServiceWorker() {
	log('generateServiceWorker...');
	return swPrecache.write(path.join('public', 'service-worker.js'), {
		staticFileGlobs: ['public' + '/**/*.{js,html,css,png,jpg,gif}'],
		stripPrefix: 'public'
	}).then(function () {
		log('generateServiceWorker done.');
	});
}

// Kick things off to start.
bundle();
<|endoftext|>


<commit_before>
/**
 * Small moving label used to show errors in operations
 */

cdb.admin.GlobalError = cdb.core.View.extend({

  initialize: function() {
    _.bindAll(this, 'hide');
  },

  templates: {
    'info': 'common/views/notifications/info',
    'error': 'common/views/notifications/info',
    'load': 'common/views/notifications/loading'
  },
  /**
   * Returns the fetched template of the passed type
   * @param  {String} type
   * @return {Function}
   */
  getTypeTemplate: function(type) {
    var url = this.templates[type]? this.templates[type] : this.templates["info"];
    var tmpl = this.getTemplate(url);
    return tmpl;
  },
  // type can be: 'info', 'error'
  showError: function(text, type, timeout) {
    timeout = timeout === undefined ? 2000: timeout;
    type || (type = 'info')

    this.$el.html(this.getTypeTemplate(type)({text: text, type: type}));

    if(this._timer) {
      clearTimeout(this._timer);
    }
    if(timeout > 0) {
      this._timer = setTimeout(this.hide, timeout);
    }
    this.show();
  },

  show: function() {
    this.$el.find("p").stop().animate({marginTop: 0}, 500);
  },

  hide: function() {
    this.$el.find("p").stop().animate({marginTop: 40}, 500);
    this._timer = 0;
  }

});
<commit_msg>added link to god<commit_after>
/**
 * Small moving label used to show errors in operations
 */

cdb.admin.GlobalError = cdb.core.View.extend({

  initialize: function() {
    _.bindAll(this, 'hide');
  },

  templates: {
    'info': 'common/views/notifications/info',
    'error': 'common/views/notifications/info',
    'load': 'common/views/notifications/loading'
  },
  /**
   * Returns the fetched template of the passed type
   * @param  {String} type
   * @return {Function}
   */
  getTypeTemplate: function(type) {
    var url = this.templates[type]? this.templates[type] : this.templates["info"];
    var tmpl = this.getTemplate(url);
    return tmpl;
  },
  // type can be: 'info', 'error'
  showError: function(text, type, timeout) {
    timeout = timeout === undefined ? 2000: timeout;
    type || (type = 'info')

    this.$el.html(this.getTypeTemplate(type)({text: text, type: type}));

    if(this._timer) {
      clearTimeout(this._timer);
    }
    if(timeout > 0) {
      this._timer = setTimeout(this.hide, timeout);
    }
    this.show();
  },

  show: function() {
    this.$el.find("p").stop().animate({marginTop: 0}, 500);
  },

  hide: function() {
    this.$el.find("p").stop().animate({marginTop: 40}, 500);
    this._timer = 0;
  },

  listenGlobal: function() {
    cdb.god.bind('error', this.showError, this);
  }

});
<|endoftext|>


<commit_before>//
// manage layers, its order and when should be shown or hiden
//
cdb.admin.LayersPanel = cdb.ui.common.TabPane.extend({

  className: 'table_panel',
  animation_time: 300,

  _TEXTS: {
    _NAME_VISUALIZATION_MSG: _t('If you want to add multiple layers you need to create a visualization first.')
  },

  events: {
    'click .add_layer': '_addLayerDialog'
  },

  initialize: function() {
    /* test */
    _.bindAll(this, 'onSortLayers', 'manageLayers', '_checkResize');

    this.vis = this.options.vis;
    this.map = this.vis.map;
    this.add_related_model(this.map);

    // Save layers panels in a sepparate object
    this.layer_panels = [];

    this.map.layers.bind('add',    this._addLayer, this);
    this.map.layers.bind('remove', this._removeLayer, this);
    this.map.layers.bind('reset',  this._resetLayers, this);
    this._addLayers(this.map.layers);

    this.isOpen = true;
    this.activeWorkView = 'table';

    $(window).bind('resize', this._checkResize);

    cdb.ui.common.TabPane.prototype.initialize.call(this);
  },

  _resetLayers: function() {
    //clean all views
    this.removeTabs();
    this._addLayers(this.map.layers);
  },

  _addLayers: function(layers) {
    // Add 'add layer' button first
    this._addLayerAddButton();

    // Add layers
    var self = this;
    layers.each(function(l) {
      self._addLayer(l);
    });

    // Bind sort
    this.bindSort();

    // Set default layer;
    this._setDefaultLayer();
  },

  _addLayer: function(layer) {
    var self = this;
    if (layer.get('type') == 'CartoDB') {
      var v = new cdb.admin.LayerPanelView({
          model: layer,
          vis: self.vis,
          user: self.options.user,
          globalError: self.options.globalError
      });

      v.bind('toggle',    self._toggle, self);
      v.bind('switchTo',  self._switchTo, self);
      v.bind('delete',    self._remove, self);

      self.addTab(layer.cid, v);
      v.setActiveWorkView(self.activeWorkView);

      self.layer_panels.push(v);

      self.trigger('switch', v);
      self._checkLayers();
    }
  },

  _setDefaultLayer: function() {
    var layer;
    var layer_id = this.vis.get('active_layer_id');

    // No layer_id, get last layer
    if (!layer_id) {
      var layer = _.last(this.layer_panels);
    }

    // Get layer from layer_id
    if (!layer) {
      for (var i in this.layer_panels) {
        var _layer = this.layer_panels[i];
        if (_layer.dataLayer.id == layer_id) {
          layer = _layer;
          break;
        }
      }
    }

    if (layer) {
      this._switchTo(layer);
    }
  },

  _removeLayer: function(layer) {
    console.log(layer, "removing!==!=!=!");
  },

  _checkLayers: function() {
    if (this.map.layers.size() > 3) {
      this._hideLayerButton();
    } else {
      this._showLayerButton();
    }
    this.manageLayers();
  },

  _addLayerAddButton: function() {
    this.$('.add_layer').remove();
    var template = this.getTemplate('table/views/add_layer');
    this.$el.prepend(template());
  },

  _showLayerButton: function() {
    this.$('section.add_layer').show();
  },

  _hideLayerButton: function() {
    this.$('section.add_layer').hide();
  },

  _addLayerDialog: function(e) {
    this.killEvent(e);
    var self = this;

    var dlg = new cdb.admin.NewLayerDialog({
      ok: function(tableName) {
        if(!self.vis.isVisualization()) {
          new cdb.admin.NameVisualization({
            msg: self._TEXTS._NAME_VISUALIZATION_MSG,
            res: function(name) {
              self.vis.changeToVisualization(function() {
                self.map.addCartodbLayerFromTable(tableName);
                self.vis.save({ name: name });
              });
            }
          }).appendToBody().open();
        } else {
          self.map.addCartodbLayerFromTable(tableName);
        }
      }
    })
    dlg.appendToBody().open();
  },

  bindSort: function() {
    this.$el
      .sortable('destroy')
      .sortable({
        axis:       "y",
        items:      "> .layer_panel",
        handle:     ".layer_info a.info",
        contaiment: this.$el,
        opacity:    0.5,
        stop:       this.onSortLayers
      });
  },

  onSortLayers: function (ev, ui) {
    this.sortLayers(ev,ui);
    this.manageLayers();
  },

  sortLayers: function(ev,ui) {
    for (var i in this._subviews) {
      var $el = this._subviews[i].$el;
      var dataLayer = this._subviews[i].dataLayer;
      var order = $(this._subviews[i].el).index('section.layer_panel') + 1;

      if ($el.hasClass('layer_panel') && dataLayer && order != dataLayer.get('order')) {
        dataLayer.save({
          'order': order
        });
      }
    }
  },

  /* Magic english */
  manageLayers: function() {
    var $active_layer = this.activePane.$el;

    // Move rest of panels
    this.$el.find('.layer_panel').removeClass('active');

    // Add active class
    $active_layer.addClass('active');

    // Set rest of layer_panels to height 60px
    // Decide later about compress them
    this.$el.find('.layer_panel').not('.layer_panel.active').css({
      height: 66
    });

    // Get previous siblings and calculate space
    var pre_size = $active_layer.prevAll('.layer_panel').size();
    var t_s = (pre_size == 0) ? 0 : (pre_size * 53);

    // Get next siblings and calculate space
    var next_size = $active_layer.nextAll('.layer_panel').size();
    var b_s = (next_size == 0) ? 0 : (next_size * 53);

    // Set available space for the active layer_space
    var offset = this.map.layers.size() > 3 ? 15 : - 25;
    $active_layer.css({
      height: this.$el.height() - (t_s + b_s) + offset
    })
  },

  /* testing resize event */
  _checkResize: function(e) {
    if (this.resize) clearTimeout(this.resize);
    var self = this;
    this.resize = setTimeout(self.manageLayers, 100);
  },

  changeWithin: function(type) {
    var width = 450
      , action = 'narrow';

    if (type == "carto") {
      width = 600;
      action = 'show';
    }

    cdb.god.trigger('panel_action', action);

    this.$el.animate({
      width: width,
      right: 0
    }, this.animation_time);
  },

  show: function(modName) {
    var width = 600,
        action = 'show';

    // Select the tab

    var mod = this.getActivePane();
    mod.tabs.activate(modName);
    mod.panels.active(modName);

    switch (modName) {
      case 'filters_mod':
      case 'wizards_mod':
      case 'infowindow_mod':
        width = 450;
        action = 'narrow';
        break;
      default:
    }

    // Show panel -> trigger
    cdb.god.trigger('panel_action', action);

    this.isOpen = true;
    this.$el.animate({
        width: width,
        right: 0
    }, this.animation_time);
  },

  hide: function(modName) {
    var panel_width = this.$el.width();

    // Hide the tab
    var mod = this.getActivePane();
    //mod.tabs.deactivate(modName);

    // Hide panel -> trigger
    cdb.god.trigger("panel_action", "hide");

    this.isOpen = false;
    this.$el.animate({
        right: 63 - panel_width
    }, this.animation_time);
  },

  _switchTo: function(l) {
    this.active(l.dataLayer.cid);
    this.options.vis.save('active_layer_id', l.dataLayer.id);
    this.trigger('switch', l);
    this.manageLayers();
  },

  _toggle: function(modName) {
    // only hide if we click on active tab
    if (this.isOpen && modName == this.getActivePane()
        .panels.activeTab) {
        this.hide(modName);
    } else {
        this.show(modName);
    }
  },

  // We need to review this method, it is not easy to
  // make operations when the view is cleaning/removing
  // For now the model destroy is happening here
  _remove: function(layer_view) {
    var layer_view_cid = layer_view.dataLayer.cid;
    var self = this;

    // Destroy layer model
    layer_view.model.destroy({
      success: function(r) {

        self.layer_panels = _.filter(self.layer_panels, function(view) {
          if (view != layer_view) return view;
        });

        self.removeTab(layer_view_cid);
        layer_view.clean();
        self.sortLayers();
        self.manageLayers();
      },
      error: function(e) {
        that.globalError.showError(that._TEXTS.error.default, 'error', 3000);
      }
    });
  },

  setActiveWorkView: function(workView) {
    this.hide();
    this.activeWorkView = workView;

    // Set active work view for all panes,
    // not only for the current one
    this.each(function(tab, pane){
      pane.setActiveWorkView(workView);
    })
  },

  clean: function() {
    $(window).unbind('resize', this._checkResize);
    if (this.resize) clearTimeout(this.resize);
    cdb.ui.common.TabPane.prototype.clean.call(this);
  }

});
<commit_msg>indentation and header main comment added to actions_menu<commit_after>
  /**
   *  Actions menu view, aka LayersPanel
   *
   *  - It needs at least visualization and user models.
   *    Globalerror to show connection or fetching errors.
   *
   *    var menu = new cdb.admin.LayersPanel({
   *      vis: vis_model,
   *      user: user_model,
   *      globalError: globalError_obj.
   *    });
   */

  cdb.admin.LayersPanel = cdb.ui.common.TabPane.extend({

    className: 'table_panel',
    animation_time: 300,

    _TEXTS: {
      name_visualization: {
        msg: _t('If you want to add multiple layers you need to create a visualization first.')
      }
    },

    events: {
      'click .add_layer': '_addLayerDialog'
    },

    initialize: function() {
      /* test */
      _.bindAll(this, 'onSortLayers', 'manageLayers', '_checkResize');

      this.vis = this.options.vis;
      this.map = this.vis.map;
      this.add_related_model(this.map);

      // Save layers panels in a sepparate object
      this.layer_panels = [];

      this.map.layers.bind('add',    this._addLayer, this);
      this.map.layers.bind('remove', this._removeLayer, this);
      this.map.layers.bind('reset',  this._resetLayers, this);
      this._addLayers(this.map.layers);

      this.isOpen = true;
      this.activeWorkView = 'table';

      $(window).bind('resize', this._checkResize);

      cdb.ui.common.TabPane.prototype.initialize.call(this);
    },

    _resetLayers: function() {
      //clean all views
      this.removeTabs();
      this._addLayers(this.map.layers);
    },

    _addLayers: function(layers) {
      // Add 'add layer' button first
      this._addLayerAddButton();

      // Add layers
      var self = this;
      layers.each(function(l) {
        self._addLayer(l);
      });

      // Bind sort
      this.bindSort();

      // Set default layer;
      this._setDefaultLayer();
    },

    _addLayer: function(layer) {
      var self = this;
      if (layer.get('type') == 'CartoDB') {
        var v = new cdb.admin.LayerPanelView({
            model: layer,
            vis: self.vis,
            user: self.options.user,
            globalError: self.options.globalError
        });

        v.bind('toggle',    self._toggle, self);
        v.bind('switchTo',  self._switchTo, self);
        v.bind('delete',    self._remove, self);

        self.addTab(layer.cid, v);
        v.setActiveWorkView(self.activeWorkView);

        self.layer_panels.push(v);

        self.trigger('switch', v);
        self._checkLayers();
      }
    },

    _setDefaultLayer: function() {
      var layer;
      var layer_id = this.vis.get('active_layer_id');

      // No layer_id, get last layer
      if (!layer_id) {
        var layer = _.last(this.layer_panels);
      }

      // Get layer from layer_id
      if (!layer) {
        for (var i in this.layer_panels) {
          var _layer = this.layer_panels[i];
          if (_layer.dataLayer.id == layer_id) {
            layer = _layer;
            break;
          }
        }
      }

      if (layer) {
        this._switchTo(layer);
      }
    },

    _removeLayer: function(layer) {
      console.log(layer, "removing!==!=!=!");
    },

    _checkLayers: function() {
      if (this.map.layers.size() > 3) {
        this._hideLayerButton();
      } else {
        this._showLayerButton();
      }
      this.manageLayers();
    },

    _addLayerAddButton: function() {
      this.$('.add_layer').remove();
      var template = this.getTemplate('table/views/add_layer');
      this.$el.prepend(template());
    },

    _showLayerButton: function() {
      this.$('section.add_layer').show();
    },

    _hideLayerButton: function() {
      this.$('section.add_layer').hide();
    },

    _addLayerDialog: function(e) {
      this.killEvent(e);
      var self = this;

      var dlg = new cdb.admin.NewLayerDialog({
        ok: function(tableName) {
          if(!self.vis.isVisualization()) {
            new cdb.admin.NameVisualization({
              msg: self._TEXTS.name_visualization.msg,
              res: function(name) {
                self.vis.changeToVisualization(function() {
                  self.map.addCartodbLayerFromTable(tableName);
                  self.vis.save({ name: name });
                });
              }
            }).appendToBody().open();
          } else {
            self.map.addCartodbLayerFromTable(tableName);
          }
        }
      })
      dlg.appendToBody().open();
    },

    bindSort: function() {
      this.$el
        .sortable('destroy')
        .sortable({
          axis:       "y",
          items:      "> .layer_panel",
          handle:     ".layer_info a.info",
          contaiment: this.$el,
          opacity:    0.5,
          stop:       this.onSortLayers
        });
    },

    onSortLayers: function (ev, ui) {
      this.sortLayers(ev,ui);
      this.manageLayers();
    },

    sortLayers: function(ev,ui) {
      for (var i in this._subviews) {
        var $el = this._subviews[i].$el;
        var dataLayer = this._subviews[i].dataLayer;
        var order = $(this._subviews[i].el).index('section.layer_panel') + 1;

        if ($el.hasClass('layer_panel') && dataLayer && order != dataLayer.get('order')) {
          dataLayer.save({
            'order': order
          });
        }
      }
    },

    /* Magic english */
    manageLayers: function() {
      var $active_layer = this.activePane.$el;

      // Move rest of panels
      this.$el.find('.layer_panel').removeClass('active');

      // Add active class
      $active_layer.addClass('active');

      // Set rest of layer_panels to height 60px
      // Decide later about compress them
      this.$el.find('.layer_panel').not('.layer_panel.active').css({
        height: 66
      });

      // Get previous siblings and calculate space
      var pre_size = $active_layer.prevAll('.layer_panel').size();
      var t_s = (pre_size == 0) ? 0 : (pre_size * 53);

      // Get next siblings and calculate space
      var next_size = $active_layer.nextAll('.layer_panel').size();
      var b_s = (next_size == 0) ? 0 : (next_size * 53);

      // Set available space for the active layer_space
      var offset = this.map.layers.size() > 3 ? 15 : - 25;
      $active_layer.css({
        height: this.$el.height() - (t_s + b_s) + offset
      })
    },

    /* testing resize event */
    _checkResize: function(e) {
      if (this.resize) clearTimeout(this.resize);
      var self = this;
      this.resize = setTimeout(self.manageLayers, 100);
    },

    changeWithin: function(type) {
      var width = 450
        , action = 'narrow';

      if (type == "carto") {
        width = 600;
        action = 'show';
      }

      cdb.god.trigger('panel_action', action);

      this.$el.animate({
        width: width,
        right: 0
      }, this.animation_time);
    },

    show: function(modName) {
      var width = 600,
          action = 'show';

      // Select the tab

      var mod = this.getActivePane();
      mod.tabs.activate(modName);
      mod.panels.active(modName);

      switch (modName) {
        case 'filters_mod':
        case 'wizards_mod':
        case 'infowindow_mod':
          width = 450;
          action = 'narrow';
          break;
        default:
      }

      // Show panel -> trigger
      cdb.god.trigger('panel_action', action);

      this.isOpen = true;
      this.$el.animate({
          width: width,
          right: 0
      }, this.animation_time);
    },

    hide: function(modName) {
      var panel_width = this.$el.width();

      // Hide the tab
      var mod = this.getActivePane();
      //mod.tabs.deactivate(modName);

      // Hide panel -> trigger
      cdb.god.trigger("panel_action", "hide");

      this.isOpen = false;
      this.$el.animate({
          right: 63 - panel_width
      }, this.animation_time);
    },

    _switchTo: function(l) {
      this.active(l.dataLayer.cid);
      this.options.vis.save('active_layer_id', l.dataLayer.id);
      this.trigger('switch', l);
      this.manageLayers();
    },

    _toggle: function(modName) {
      // only hide if we click on active tab
      if (this.isOpen && modName == this.getActivePane()
          .panels.activeTab) {
          this.hide(modName);
      } else {
          this.show(modName);
      }
    },

    // We need to review this method, it is not easy to
    // make operations when the view is cleaning/removing
    // For now the model destroy is happening here
    _remove: function(layer_view) {
      var layer_view_cid = layer_view.dataLayer.cid;
      var self = this;

      // Destroy layer model
      layer_view.model.destroy({
        success: function(r) {

          self.layer_panels = _.filter(self.layer_panels, function(view) {
            if (view != layer_view) return view;
          });

          self.removeTab(layer_view_cid);
          layer_view.clean();
          self.sortLayers();
          self.manageLayers();
        },
        error: function(e) {
          that.globalError.showError(that._TEXTS.error.default, 'error', 3000);
        }
      });
    },

    setActiveWorkView: function(workView) {
      this.hide();
      this.activeWorkView = workView;

      // Set active work view for all panes,
      // not only for the current one
      this.each(function(tab, pane){
        pane.setActiveWorkView(workView);
      })
    },

    clean: function() {
      $(window).unbind('resize', this._checkResize);
      if (this.resize) clearTimeout(this.resize);
      cdb.ui.common.TabPane.prototype.clean.call(this);
    }
  });<|endoftext|>


<commit_before>import path from 'path';
import webpack from 'webpack';
import Dotenv from 'dotenv-webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
import TerserWebpackPlugin from 'terser-webpack-plugin';
import resolveFrom from 'resolve-from';

import babelLoader, { nodeModulesBabelLoader } from '../common/babel-loader';
import { nodeModulesPaths, loadEnv } from '../config/utils';
import { getPreviewHeadHtml, getPreviewBodyHtml } from '../utils/template';

const reactPaths = {};
try {
  reactPaths.react = path.dirname(resolveFrom(process.cwd(), 'react/package.json'));
  reactPaths['react-dom'] = path.dirname(resolveFrom(process.cwd(), 'react-dom/package.json'));
} catch (e) {
  //
}

export default ({
  configDir,
  babelOptions,
  entries,
  outputDir = path.join('.', 'public'),
  quiet,
  packageJson,
  configType,
}) => {
  const { raw, stringified } = loadEnv({ production: true });
  const isProd = configType === 'PRODUCTION';

  return {
    mode: isProd ? 'production' : 'development',
    bail: isProd,
    devtool: '#cheap-module-source-map',
    entry: entries,
    output: {
      path: path.join(process.cwd(), outputDir),
      filename: '[name].[hash].bundle.js',
      publicPath: '',
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: `iframe.html`,
        chunksSortMode: 'none',
        alwaysWriteToDisk: true,
        inject: false,
        templateParameters: (compilation, files, options) => ({
          compilation,
          files,
          options,
          version: packageJson.version,
          headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
          dlls: [],
          bodyHtmlSnippet: getPreviewBodyHtml(),
        }),
        template: require.resolve(`../templates/index.ejs`),
      }),
      new webpack.DefinePlugin({ 'process.env': stringified }),
      isProd ? null : new WatchMissingNodeModulesPlugin(nodeModulesPaths),
      isProd ? null : new webpack.HotModuleReplacementPlugin(),
      new CaseSensitivePathsPlugin(),
      quiet ? null : new webpack.ProgressPlugin(),
      new Dotenv({ silent: true }),
    ].filter(Boolean),
    module: {
      rules: [
        babelLoader(babelOptions),
        nodeModulesBabelLoader,
        {
          test: /\.md$/,
          use: [
            {
              loader: require.resolve('raw-loader'),
            },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.mjs', '.js', '.jsx', '.json'],
      modules: ['node_modules'].concat(raw.NODE_PATH || []),
      mainFields: ['browser', 'main', 'module'],
      alias: {
        'core-js': path.dirname(require.resolve('core-js/package.json')),
        ...reactPaths,
      },
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      runtimeChunk: true,
      minimizer: [
        new TerserWebpackPlugin({
          cache: true,
          parallel: true,
          sourceMap: true,
          terserOptions: {
            mangle: false,
          },
        }),
      ],
    },
    performance: {
      hints: isProd ? 'warning' : false,
    },
  };
};
<commit_msg>Fix: Don't mangle function names for production builds<commit_after>import path from 'path';
import webpack from 'webpack';
import Dotenv from 'dotenv-webpack';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import CaseSensitivePathsPlugin from 'case-sensitive-paths-webpack-plugin';
import WatchMissingNodeModulesPlugin from 'react-dev-utils/WatchMissingNodeModulesPlugin';
import TerserWebpackPlugin from 'terser-webpack-plugin';
import resolveFrom from 'resolve-from';

import babelLoader, { nodeModulesBabelLoader } from '../common/babel-loader';
import { nodeModulesPaths, loadEnv } from '../config/utils';
import { getPreviewHeadHtml, getPreviewBodyHtml } from '../utils/template';

const reactPaths = {};
try {
  reactPaths.react = path.dirname(resolveFrom(process.cwd(), 'react/package.json'));
  reactPaths['react-dom'] = path.dirname(resolveFrom(process.cwd(), 'react-dom/package.json'));
} catch (e) {
  //
}

export default ({
  configDir,
  babelOptions,
  entries,
  outputDir = path.join('.', 'public'),
  quiet,
  packageJson,
  configType,
}) => {
  const { raw, stringified } = loadEnv({ production: true });
  const isProd = configType === 'PRODUCTION';

  return {
    mode: isProd ? 'production' : 'development',
    bail: isProd,
    devtool: '#cheap-module-source-map',
    entry: entries,
    output: {
      path: path.join(process.cwd(), outputDir),
      filename: '[name].[hash].bundle.js',
      publicPath: '',
    },
    plugins: [
      new HtmlWebpackPlugin({
        filename: `iframe.html`,
        chunksSortMode: 'none',
        alwaysWriteToDisk: true,
        inject: false,
        templateParameters: (compilation, files, options) => ({
          compilation,
          files,
          options,
          version: packageJson.version,
          headHtmlSnippet: getPreviewHeadHtml(configDir, process.env),
          dlls: [],
          bodyHtmlSnippet: getPreviewBodyHtml(),
        }),
        template: require.resolve(`../templates/index.ejs`),
      }),
      new webpack.DefinePlugin({ 'process.env': stringified }),
      isProd ? null : new WatchMissingNodeModulesPlugin(nodeModulesPaths),
      isProd ? null : new webpack.HotModuleReplacementPlugin(),
      new CaseSensitivePathsPlugin(),
      quiet ? null : new webpack.ProgressPlugin(),
      new Dotenv({ silent: true }),
    ].filter(Boolean),
    module: {
      rules: [
        babelLoader(babelOptions),
        nodeModulesBabelLoader,
        {
          test: /\.md$/,
          use: [
            {
              loader: require.resolve('raw-loader'),
            },
          ],
        },
      ],
    },
    resolve: {
      extensions: ['.mjs', '.js', '.jsx', '.json'],
      modules: ['node_modules'].concat(raw.NODE_PATH || []),
      mainFields: ['browser', 'main', 'module'],
      alias: {
        'core-js': path.dirname(require.resolve('core-js/package.json')),
        ...reactPaths,
      },
    },
    optimization: {
      splitChunks: {
        chunks: 'all',
      },
      runtimeChunk: true,
      minimizer: [
        new TerserWebpackPlugin({
          cache: true,
          parallel: true,
          sourceMap: true,
          terserOptions: {
            mangle: false,
            keep_fnames: true,
          },
        }),
      ],
    },
    performance: {
      hints: isProd ? 'warning' : false,
    },
  };
};
<|endoftext|>


<commit_before>goog.provide('ol.MapBrowserEvent');
goog.provide('ol.MapBrowserEvent.EventType');
goog.provide('ol.MapBrowserEventHandler');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');

goog.require('ol.Coordinate');
goog.require('ol.MapEvent');
goog.require('ol.Pixel');
goog.require('ol.pointer.PointerEventHandler');

/**
 * @constructor
 * @extends {ol.MapEvent}
 * @implements {oli.MapBrowserEvent}
 * @param {string} type Event type.
 * @param {ol.Map} map Map.
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @param {?oli.FrameState=} opt_frameState Frame state.
 * @todo stability experimental
 */
ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) {

  goog.base(this, type, map, opt_frameState);

  /**
   * @const
   * @type {goog.events.BrowserEvent}
   */
  this.browserEvent = browserEvent;

  /**
   * @const
   * @type {Event}
   */
  this.originalEvent = browserEvent.getBrowserEvent();

  /**
   * @type {ol.Coordinate}
   */
  this.coordinate = map.getEventCoordinate(this.originalEvent);

  /**
   * @type {ol.Pixel}
   */
  this.pixel = map.getEventPixel(this.originalEvent);

};
goog.inherits(ol.MapBrowserEvent, ol.MapEvent);

/**
 * Prevents the default browser action.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault
 * @override
 * @todo stability experimental
 */
ol.MapBrowserEvent.prototype.preventDefault = function() {
  goog.base(this, 'preventDefault');
  this.browserEvent.preventDefault();
};

/**
 * Prevents further propagation of the current event.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
 * @override
 * @todo stability experimental
 */
ol.MapBrowserEvent.prototype.stopPropagation = function() {
  goog.base(this, 'stopPropagation');
  this.browserEvent.stopPropagation();
};

/**
 * @param {ol.Map} map The map with the viewport to listen to events on.
 * @constructor
 * @extends {goog.events.EventTarget}
 */
ol.MapBrowserEventHandler = function(map) {

  goog.base(this);

  /**
   * This is the element that we will listen to the real events on.
   * @type {ol.Map}
   * @private
   */
  this.map_ = map;

  /**
   * @type {number}
   * @private
   */
  this.clickTimeoutId_ = 0;

  /**
   * @type {boolean}
   * @private
   */
  this.dragged_ = false;

  /**
   * @type {Array.<number>}
   * @private
   */
  this.dragListenerKeys_ = null;

  /**
   * @type {goog.events.Key}
   * @private
   */
  this.pointerdownListenerKey_ = null;

  this.down_ = null;

  var element = this.map_.getViewport();

  /**
   * @type {ol.pointer.PointerEventHandler}
   * @private
   */
  this.pointerEventHandler_ = new ol.pointer.PointerEventHandler(element);
  this.pointerdownListenerKey_ = goog.events.listen(this.pointerEventHandler_,
      ol.pointer.EventType.POINTERDOWN,
      this.handlePointerDown_, false, this);

  this.relayedListenerKeys_ = [
    goog.events.listen(this.pointerEventHandler_,
        ol.pointer.EventType.POINTERMOVE,
        this.relayEvent_, false, this)
  ];
};
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);

/**
 * Get the last "down" type event.  This will be set on mousedown,
 * touchstart, and pointerdown.
 * @return {goog.events.BrowserEvent} The most recent "down" type event (or null
 * if none have occurred).
 */
ol.MapBrowserEventHandler.prototype.getDown = function() {
  return this.down_;
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
  if (this.clickTimeoutId_ !== 0) {
    // double-click
    goog.global.clearTimeout(this.clickTimeoutId_);
    this.clickTimeoutId_ = 0;
    var newEvent = new ol.MapBrowserEvent(
        ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent);
    this.dispatchEvent(newEvent);
  } else {
    // click

    if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
      // In IE 7-8, referring to the original event object after the current
      // call stack causes "member not found" exceptions, such as in the timeout
      // we use here.
      var ev = /** @type {Event} */ (
          goog.object.clone(browserEvent.getBrowserEvent()));
      this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
        this.clickTimeoutId_ = 0;
        var newEvent = new ol.MapBrowserEvent(
            ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_,
            new goog.events.BrowserEvent(ev, browserEvent.currentTarget));
        this.dispatchEvent(newEvent);
      }, this), 250);
    } else {
      this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
        this.clickTimeoutId_ = 0;
        var newEvent = new ol.MapBrowserEvent(
            ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, browserEvent);
        this.dispatchEvent(newEvent);
      }, this), 250);
    }
  }
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
  if (this.down_) {
    goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
    this.dragListenerKeys_ = null;
    if (this.dragged_) {
      var newEvent = new ol.MapBrowserEvent(
          ol.MapBrowserEvent.EventType.DRAGEND, this.map_, browserEvent);
      this.dispatchEvent(newEvent);
    } else if (browserEvent.isMouseActionButton()) {
      this.emulateClick_(browserEvent);
    }
  }
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
    function(browserEvent) {
  var newEvent = new ol.MapBrowserEvent(
      ol.MapBrowserEvent.EventType.DOWN, this.map_, browserEvent);
  this.dispatchEvent(newEvent);
  this.down_ = browserEvent;
  this.dragged_ = false;
  this.dragListenerKeys_ = [
    goog.events.listen(this.pointerEventHandler_,
        ol.MapBrowserEvent.EventType.POINTERMOVE,
        this.handlePointerMove_, false, this),
    goog.events.listen(this.pointerEventHandler_,
        ol.MapBrowserEvent.EventType.POINTERUP,
        this.handlePointerUp_, false, this)
  ];
  // prevent browser image dragging with the dom renderer
  browserEvent.preventDefault();
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
    function(browserEvent) {
  var newEvent;
  if (!this.dragged_) {
    this.dragged_ = true;
    newEvent = new ol.MapBrowserEvent(
        ol.MapBrowserEvent.EventType.DRAGSTART, this.map_, this.down_);
    this.dispatchEvent(newEvent);
  }
  newEvent = new ol.MapBrowserEvent(
      ol.MapBrowserEvent.EventType.DRAG, this.map_, browserEvent);
  this.dispatchEvent(newEvent);
};

/**
 * FIXME empty description for jsdoc
 */
ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
  if (!goog.isNull(this.relayedListenerKeys_)) {
    goog.array.forEach(this.relayedListenerKeys_, goog.events.unlistenByKey);
    this.relayedListenerKeys_ = null;
  }
  if (!goog.isNull(this.mousedownListenerKey_)) {
    goog.events.unlistenByKey(this.mousedownListenerKey_);
    this.mousedownListenerKey_ = null;
  }
  if (!goog.isNull(this.pointerdownListenerKey_)) {
    goog.events.unlistenByKey(this.pointerdownListenerKey_);
    this.pointerdownListenerKey_ = null;
  }
  if (!goog.isNull(this.touchstartListenerKey_)) {
    goog.events.unlistenByKey(this.touchstartListenerKey_);
    this.touchstartListenerKey_ = null;
  }
  if (!goog.isNull(this.dragListenerKeys_)) {
    goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
    this.dragListenerKeys_ = null;
  }
  if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE &&
      !goog.isNull(this.ieDblclickListenerKey_)) {
    goog.events.unlistenByKey(this.ieDblclickListenerKey_);
    this.ieDblclickListenerKey_ = null;
  }
  goog.base(this, 'disposeInternal');
};

/**
 * Wrap and relay a browser event.  Note that this requires that the type
 * string for the MapBrowserEvent matches the BrowserEvent type.
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.relayEvent_ = function(browserEvent) {
  this.dispatchEvent(new ol.MapBrowserEvent(
      browserEvent.type, this.map_, browserEvent));
};

/**
 * Constants for event names.
 * @enum {string}
 */
ol.MapBrowserEvent.EventType = {
  CLICK: goog.events.EventType.CLICK,
  DBLCLICK: goog.events.EventType.DBLCLICK,
  DRAGSTART: 'dragstart',
  DRAG: 'drag',
  DRAGEND: 'dragend',
  DOWN: 'down',

  MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
  SINGLECLICK: 'singleclick',
  TOUCHSTART: goog.events.EventType.TOUCHSTART,
  TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
  TOUCHEND: goog.events.EventType.TOUCHEND,

  POINTERMOVE: 'pointermove',
  POINTERDOWN: 'pointerdown',
  POINTERUP: 'pointerup',
  POINTEROVER: 'pointerover',
  POINTERENTER: 'pointerenter',
  POINTERLEAVE: 'pointerleave',
  POINTERCANCEL: 'pointercancel'
};
<commit_msg>base interactions for pointer events on existing touch interactions<commit_after>goog.provide('ol.MapBrowserEvent');
goog.provide('ol.MapBrowserEvent.EventType');
goog.provide('ol.MapBrowserEventHandler');

goog.require('goog.array');
goog.require('goog.asserts');
goog.require('goog.events');
goog.require('goog.events.BrowserEvent');
goog.require('goog.events.EventTarget');
goog.require('goog.events.EventType');

goog.require('ol.Coordinate');
goog.require('ol.MapEvent');
goog.require('ol.Pixel');
goog.require('ol.pointer.PointerEventHandler');

/**
 * @constructor
 * @extends {ol.MapEvent}
 * @implements {oli.MapBrowserEvent}
 * @param {string} type Event type.
 * @param {ol.Map} map Map.
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @param {?oli.FrameState=} opt_frameState Frame state.
 * @todo stability experimental
 */
ol.MapBrowserEvent = function(type, map, browserEvent, opt_frameState) {

  goog.base(this, type, map, opt_frameState);

  /**
   * @const
   * @type {goog.events.BrowserEvent}
   */
  this.browserEvent = browserEvent;

  /**
   * @const
   * @type {Event}
   */
  this.originalEvent = browserEvent.getBrowserEvent();

  /**
   * @type {ol.Coordinate}
   */
  this.coordinate = map.getEventCoordinate(this.originalEvent);

  /**
   * @type {ol.Pixel}
   */
  this.pixel = map.getEventPixel(this.originalEvent);

};
goog.inherits(ol.MapBrowserEvent, ol.MapEvent);

/**
 * Prevents the default browser action.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault
 * @override
 * @todo stability experimental
 */
ol.MapBrowserEvent.prototype.preventDefault = function() {
  goog.base(this, 'preventDefault');
  this.browserEvent.preventDefault();
};

/**
 * Prevents further propagation of the current event.
 * @see https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation
 * @override
 * @todo stability experimental
 */
ol.MapBrowserEvent.prototype.stopPropagation = function() {
  goog.base(this, 'stopPropagation');
  this.browserEvent.stopPropagation();
};

/**
 * @param {ol.Map} map The map with the viewport to listen to events on.
 * @constructor
 * @extends {goog.events.EventTarget}
 */
ol.MapBrowserEventHandler = function(map) {

  goog.base(this);

  /**
   * This is the element that we will listen to the real events on.
   * @type {ol.Map}
   * @private
   */
  this.map_ = map;

  /**
   * @type {number}
   * @private
   */
  this.clickTimeoutId_ = 0;

  /**
   * @type {boolean}
   * @private
   */
  this.dragged_ = false;

  /**
   * @type {Array.<number>}
   * @private
   */
  this.dragListenerKeys_ = null;

  /**
   * @type {goog.events.Key}
   * @private
   */
  this.pointerdownListenerKey_ = null;

  this.down_ = null;

  var element = this.map_.getViewport();

  /**
   * @type {number}
   * @private
   */
  this.activePointers_ = 0;

  /**
   * @type {ol.pointer.PointerEventHandler}
   * @private
   */
  this.pointerEventHandler_ = new ol.pointer.PointerEventHandler(element);
  this.pointerdownListenerKey_ = goog.events.listen(this.pointerEventHandler_,
      ol.pointer.EventType.POINTERDOWN,
      this.handlePointerDown_, false, this);
};
goog.inherits(ol.MapBrowserEventHandler, goog.events.EventTarget);

/**
 * Get the last "down" type event.  This will be set on mousedown,
 * touchstart, and pointerdown.
 * @return {goog.events.BrowserEvent} The most recent "down" type event (or null
 * if none have occurred).
 */
ol.MapBrowserEventHandler.prototype.getDown = function() {
  return this.down_;
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.emulateClick_ = function(browserEvent) {
  if (this.clickTimeoutId_ !== 0) {
    // double-click
    goog.global.clearTimeout(this.clickTimeoutId_);
    this.clickTimeoutId_ = 0;
    var newEvent = new ol.MapBrowserEvent(
        ol.MapBrowserEvent.EventType.DBLCLICK, this.map_, browserEvent);
    this.dispatchEvent(newEvent);
  } else {
    // click

    if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE) {
      // In IE 7-8, referring to the original event object after the current
      // call stack causes "member not found" exceptions, such as in the timeout
      // we use here.
      var ev = /** @type {Event} */ (
          goog.object.clone(browserEvent.getBrowserEvent()));
      this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
        this.clickTimeoutId_ = 0;
        var newEvent = new ol.MapBrowserEvent(
            ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_,
            new goog.events.BrowserEvent(ev, browserEvent.currentTarget));
        this.dispatchEvent(newEvent);
      }, this), 250);
    } else {
      this.clickTimeoutId_ = goog.global.setTimeout(goog.bind(function() {
        this.clickTimeoutId_ = 0;
        var newEvent = new ol.MapBrowserEvent(
            ol.MapBrowserEvent.EventType.SINGLECLICK, this.map_, browserEvent);
        this.dispatchEvent(newEvent);
      }, this), 250);
    }
  }
};

/**
 * Keeps track on how many pointers are currently active.
 *
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.updateActivePointers_ = function(browserEvent) {
  var event = browserEvent.getBrowserEvent();

  if (event.type == ol.MapBrowserEvent.EventType.POINTERUP ||
      event.type == ol.MapBrowserEvent.EventType.POINTERCANCEL) {
    this.activePointers_--;
  } else if (event.type == ol.MapBrowserEvent.EventType.POINTERDOWN) {
    this.activePointers_++;
  }
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerUp_ = function(browserEvent) {
  this.updateActivePointers_(browserEvent);
  var newEvent = new ol.MapBrowserEvent(
      ol.MapBrowserEvent.EventType.TOUCHEND, this.map_, browserEvent);
  this.dispatchEvent(newEvent);

  if (this.activePointers_ <= 0) {
    goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
    this.dragListenerKeys_ = null;
  }

  // We emulate click event on left mouse button click, touch contact, and pen
  // contact. isMouseActionButton returns true in these cases (evt.button is set
  // to 0).
  // See http://www.w3.org/TR/pointerevents/#button-states .
  if (!this.dragged_ && browserEvent.isMouseActionButton()) {
    goog.asserts.assert(!goog.isNull(this.down_));
    this.emulateClick_(this.down_);
  }
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerDown_ =
    function(browserEvent) {
  this.updateActivePointers_(browserEvent);
  var newEvent = new ol.MapBrowserEvent(
      ol.MapBrowserEvent.EventType.TOUCHSTART, this.map_, browserEvent);
  this.dispatchEvent(newEvent);

  this.down_ = browserEvent;
  this.dragged_ = false;

  if (goog.isNull(this.dragListenerKeys_)) {
    this.dragListenerKeys_ = [
      goog.events.listen(this.pointerEventHandler_,
          ol.MapBrowserEvent.EventType.POINTERMOVE,
          this.handlePointerMove_, false, this),
      goog.events.listen(this.pointerEventHandler_,
          [ol.MapBrowserEvent.EventType.POINTERUP,
           ol.MapBrowserEvent.EventType.POINTERCANCEL],
          this.handlePointerUp_, false, this)
    ];
  }

  // FIXME check if/when this is necessary
  // prevent context menu
  browserEvent.preventDefault();
};

/**
 * @param {goog.events.BrowserEvent} browserEvent Browser event.
 * @private
 */
ol.MapBrowserEventHandler.prototype.handlePointerMove_ =
    function(browserEvent) {
  // Fix IE10 on windows Surface : When you tap the tablet, it triggers
  // multiple pointermove events between pointerdown and pointerup with
  // the exact same coordinates of the pointerdown event. To avoid a
  // 'false' touchmove event to be dispatched , we test if the pointer
  // effectively moved.
  if (browserEvent.clientX != this.down_.clientX ||
      browserEvent.clientY != this.down_.clientY) {
    this.dragged_ = true;
    var newEvent = new ol.MapBrowserEvent(
        ol.MapBrowserEvent.EventType.TOUCHMOVE, this.map_, browserEvent);
    this.dispatchEvent(newEvent);
  }

  // Some native android browser triggers mousemove events during small period
  // of time. See: https://code.google.com/p/android/issues/detail?id=5491 or
  // https://code.google.com/p/android/issues/detail?id=19827
  // ex: Galaxy Tab P3110 + Android 4.1.1
  browserEvent.preventDefault();
};

/**
 * FIXME empty description for jsdoc
 */
ol.MapBrowserEventHandler.prototype.disposeInternal = function() {
  if (!goog.isNull(this.pointerdownListenerKey_)) {
    goog.events.unlistenByKey(this.pointerdownListenerKey_);
    this.pointerdownListenerKey_ = null;
  }
  if (!goog.isNull(this.dragListenerKeys_)) {
    goog.array.forEach(this.dragListenerKeys_, goog.events.unlistenByKey);
    this.dragListenerKeys_ = null;
  }
  if (ol.LEGACY_IE_SUPPORT && ol.IS_LEGACY_IE &&
      !goog.isNull(this.ieDblclickListenerKey_)) {
    goog.events.unlistenByKey(this.ieDblclickListenerKey_);
    this.ieDblclickListenerKey_ = null;
  }
  goog.base(this, 'disposeInternal');
};

/**
 * Constants for event names.
 * @enum {string}
 */
ol.MapBrowserEvent.EventType = {
  CLICK: goog.events.EventType.CLICK,
  DBLCLICK: goog.events.EventType.DBLCLICK,
  DRAGSTART: 'dragstart',
  DRAG: 'drag',
  DRAGEND: 'dragend',
  DOWN: 'down',

  MOUSEMOVE: goog.events.EventType.MOUSEMOVE,
  SINGLECLICK: 'singleclick',
  TOUCHSTART: goog.events.EventType.TOUCHSTART,
  TOUCHMOVE: goog.events.EventType.TOUCHMOVE,
  TOUCHEND: goog.events.EventType.TOUCHEND,

  POINTERMOVE: 'pointermove',
  POINTERDOWN: 'pointerdown',
  POINTERUP: 'pointerup',
  POINTEROVER: 'pointerover',
  POINTERENTER: 'pointerenter',
  POINTERLEAVE: 'pointerleave',
  POINTERCANCEL: 'pointercancel'
};
<|endoftext|>


<commit_before>class Entity {
  owner = null;
  constructor(owner) {
    this.owner = owner;
  }

  /**
   * This also tracks debuffs in the exact same array. There are no parameters to filter results by debuffs. I don't think this should be necessary as debuffs and buffs usually have different spell IDs.
   */

  buffs = [];

  /**
   * @param {number} timestamp - Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime - Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @returns {function} The buffs within the time period.
   */
  static activeAtTimestampFilter(timestamp, bufferTime = 0, minimalActiveTime = 0) {
    return buff => (timestamp - minimalActiveTime) >= buff.start && (buff.end === null || (buff.end + bufferTime) >= timestamp);
  }
  static spellIdFilter(spellId) {
    const nSpellId = Number(spellId);
    return buff => buff.ability.guid === nSpellId;
  }
  static sourceIdFilter(sourceID) {
    if (sourceID === null) {
      return () => true;
    }
    return buff => buff.sourceID === sourceID;
  }

  activeBuffs(forTimestamp = null, bufferTime = 0, minimalActiveTime = 0) {
    const currentTimestamp = forTimestamp !== null ? forTimestamp : this.owner.currentTimestamp;
    return this.buffs.filter(this.constructor.activeAtTimestampFilter(currentTimestamp, bufferTime, minimalActiveTime));
  }

  /**
   * @param {number} spellId buff ID to check for
   * @param {number} forTimestamp Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @param {number} sourceID - source ID the buff must have come from, or any source if null
   * @returns {boolean} - Whether the buff is present with the given specifications.
   */
  hasBuff(spellId, forTimestamp = null, bufferTime = 0, minimalActiveTime = 0, sourceID = null) {
    return this.getBuff(spellId, forTimestamp, bufferTime, minimalActiveTime, sourceID) !== undefined;
  }

  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} forTimestamp Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {Object} - A buff with the given specifications. The buff object will have all the properties of the associated applybuff event, along with a start timestamp, an end timestamp if the buff has fallen, and an isDebuff flag. If multiple buffs meet the specifications, there's no guarantee which you'll get (this could happen if multiple spells with the same spellId but from different sources are on the same target)
   */
  getBuff(spellId, forTimestamp = null, bufferTime = 0, minimalActiveTime = 0, sourceID = null) {
    const currentTimestamp = forTimestamp !== null ? forTimestamp : this.owner.currentTimestamp;
    const isCorrectSpell = this.constructor.spellIdFilter(spellId);
    const isActive = this.constructor.activeAtTimestampFilter(currentTimestamp, bufferTime, minimalActiveTime);
    const isCorrectSource = this.constructor.sourceIdFilter(sourceID);
    return this.buffs.find(buff => isCorrectSpell(buff) && isActive(buff) && isCorrectSource(buff));
  }

  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {array} The buff activations.
   */
  getBuffHistory(spellId, sourceID = null) {
    const isCorrectSpell = this.constructor.spellIdFilter(spellId);
    const isCorrectSource = this.constructor.sourceIdFilter(sourceID);
    return this.buffs.filter(buff => isCorrectSpell(buff) && isCorrectSource(buff));
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - Time (in ms) the specified buff has been active.
   */
  getBuffUptime(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID)
      .reduce((uptime, buff) => uptime + (buff.end !== null ? buff.end : this.owner.currentTimestamp) - buff.start, 0);
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number|null} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - The number of times the specified buff has been applied (only applications count, not stack changes or refreshes).
   */
  getBuffTriggerCount(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID).length;
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number|null} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - Time (in ms) the specified buff has been active weighted by the number of stacks active.
   *      For example if buff was up for 10000ms with 1 stack and 20000ms with 2 stacks, would return 50000.
   */
  getStackWeightedBuffUptime(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID)
      .reduce((totalUptime, buff) => {
        let startTime;
        let startStacks;
        const buffUptime = buff.stackHistory.reduce((stackUptime, stack) => {
          const result = !startTime ? 0 : (stack.timestamp - startTime) * startStacks;
          startTime = stack.timestamp;
          startStacks = stack.stacks;
          return stackUptime + result;
        }, 0);
        return totalUptime + buffUptime;
      }, 0);
  }
}

export default Entity;
<commit_msg>Fix weighted buff calculation when buff doesnt expire<commit_after>class Entity {
  owner = null;
  constructor(owner) {
    this.owner = owner;
  }

  /**
   * This also tracks debuffs in the exact same array. There are no parameters to filter results by debuffs. I don't think this should be necessary as debuffs and buffs usually have different spell IDs.
   */

  buffs = [];

  /**
   * @param {number} timestamp - Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime - Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @returns {function} The buffs within the time period.
   */
  static activeAtTimestampFilter(timestamp, bufferTime = 0, minimalActiveTime = 0) {
    return buff => (timestamp - minimalActiveTime) >= buff.start && (buff.end === null || (buff.end + bufferTime) >= timestamp);
  }
  static spellIdFilter(spellId) {
    const nSpellId = Number(spellId);
    return buff => buff.ability.guid === nSpellId;
  }
  static sourceIdFilter(sourceID) {
    if (sourceID === null) {
      return () => true;
    }
    return buff => buff.sourceID === sourceID;
  }

  activeBuffs(forTimestamp = null, bufferTime = 0, minimalActiveTime = 0) {
    const currentTimestamp = forTimestamp !== null ? forTimestamp : this.owner.currentTimestamp;
    return this.buffs.filter(this.constructor.activeAtTimestampFilter(currentTimestamp, bufferTime, minimalActiveTime));
  }

  /**
   * @param {number} spellId buff ID to check for
   * @param {number} forTimestamp Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @param {number} sourceID - source ID the buff must have come from, or any source if null
   * @returns {boolean} - Whether the buff is present with the given specifications.
   */
  hasBuff(spellId, forTimestamp = null, bufferTime = 0, minimalActiveTime = 0, sourceID = null) {
    return this.getBuff(spellId, forTimestamp, bufferTime, minimalActiveTime, sourceID) !== undefined;
  }

  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} forTimestamp Timestamp (in ms) to be considered, or the current timestamp if null. Won't work right for timestamps after the currentTimestamp.
   * @param {number} bufferTime Time (in ms) after buff's expiration where it will still be included. There's a bug in the combat log where if a spell consumes a buff that buff may disappear a short time before the heal or damage event it's buffing is logged. This can sometimes go up to hundreds of milliseconds.
   * @param {number} minimalActiveTime - Time (in ms) the buff must have been active before timestamp for it to be included.
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {Object} - A buff with the given specifications. The buff object will have all the properties of the associated applybuff event, along with a start timestamp, an end timestamp if the buff has fallen, and an isDebuff flag. If multiple buffs meet the specifications, there's no guarantee which you'll get (this could happen if multiple spells with the same spellId but from different sources are on the same target)
   */
  getBuff(spellId, forTimestamp = null, bufferTime = 0, minimalActiveTime = 0, sourceID = null) {
    const currentTimestamp = forTimestamp !== null ? forTimestamp : this.owner.currentTimestamp;
    const isCorrectSpell = this.constructor.spellIdFilter(spellId);
    const isActive = this.constructor.activeAtTimestampFilter(currentTimestamp, bufferTime, minimalActiveTime);
    const isCorrectSource = this.constructor.sourceIdFilter(sourceID);
    return this.buffs.find(buff => isCorrectSpell(buff) && isActive(buff) && isCorrectSource(buff));
  }

  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {array} The buff activations.
   */
  getBuffHistory(spellId, sourceID = null) {
    const isCorrectSpell = this.constructor.spellIdFilter(spellId);
    const isCorrectSource = this.constructor.sourceIdFilter(sourceID);
    return this.buffs.filter(buff => isCorrectSpell(buff) && isCorrectSource(buff));
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - Time (in ms) the specified buff has been active.
   */
  getBuffUptime(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID)
      .reduce((uptime, buff) => uptime + (buff.end !== null ? buff.end : this.owner.currentTimestamp) - buff.start, 0);
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number|null} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - The number of times the specified buff has been applied (only applications count, not stack changes or refreshes).
   */
  getBuffTriggerCount(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID).length;
  }
  /**
   * @param {number} spellId - buff ID to check for
   * @param {number|null} sourceID - source ID the buff must have come from, or any source if null.
   * @returns {number} - Time (in ms) the specified buff has been active weighted by the number of stacks active.
   *      For example if buff was up for 10000ms with 1 stack and 20000ms with 2 stacks, would return 50000.
   */
  getStackWeightedBuffUptime(spellId, sourceID = null) {
    return this.getBuffHistory(spellId, sourceID)
      .reduce((totalUptime, buff) => {
        let startTime;
        let startStacks;
        const buffUptime = buff.stackHistory.reduce((stackUptime, stack, idx, arr) => {
          let result = !startTime ? 0 : (stack.timestamp - startTime) * startStacks;
          startTime = stack.timestamp;
          startStacks = stack.stacks;
          if (buff.end === null && idx === arr.length - 1) {
            // If the buff instance didn't end (usually because it was still active at the end of the fight) we need to manually account for it
            const finalStackUptime = this.owner.currentTimestamp - startTime;
            const weighted = finalStackUptime * startStacks;
            result += weighted;
          }
          return stackUptime + result;
        }, 0);
        return totalUptime + buffUptime;
      }, 0);
  }
}

export default Entity;
<|endoftext|>


<commit_before>import React, { Component } from 'react'

import { getSDK, isMediaStream, supportsWebKitPresentationMode } from '../utils'
import { AUDIO_EXTENSIONS, HLS_EXTENSIONS, DASH_EXTENSIONS } from '../patterns'

const IOS = typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
const HLS_SDK_URL = 'https://cdn.jsdelivr.net/npm/hls.js@VERSION/dist/hls.min.js'
const HLS_GLOBAL = 'Hls'
const DASH_SDK_URL = 'https://cdnjs.cloudflare.com/ajax/libs/dashjs/VERSION/dash.all.min.js'
const DASH_GLOBAL = 'dashjs'
const MATCH_DROPBOX_URL = /www\.dropbox\.com\/.+/

export default class FilePlayer extends Component {
  static displayName = 'FilePlayer'

  componentDidMount () {
    this.props.onMount && this.props.onMount(this)
    this.addListeners(this.player)
    if (IOS) {
      this.player.load()
    }
  }

  componentDidUpdate (prevProps) {
    if (this.shouldUseAudio(this.props) !== this.shouldUseAudio(prevProps)) {
      this.removeListeners(this.prevPlayer)
      this.addListeners(this.player)
    }
  }

  componentWillUnmount () {
    this.removeListeners(this.player)
    if (this.hls) {
      this.hls.destroy()
    }
  }

  addListeners (player) {
    const { playsinline } = this.props
    player.addEventListener('canplay', this.onReady)
    player.addEventListener('play', this.onPlay)
    player.addEventListener('waiting', this.onBuffer)
    player.addEventListener('playing', this.onBufferEnd)
    player.addEventListener('pause', this.onPause)
    player.addEventListener('seeked', this.onSeek)
    player.addEventListener('ended', this.onEnded)
    player.addEventListener('error', this.onError)
    player.addEventListener('enterpictureinpicture', this.onEnablePIP)
    player.addEventListener('leavepictureinpicture', this.onDisablePIP)
    player.addEventListener('webkitpresentationmodechanged', this.onPresentationModeChange)
    if (playsinline) {
      player.setAttribute('playsinline', '')
      player.setAttribute('webkit-playsinline', '')
      player.setAttribute('x5-playsinline', '')
    }
  }

  removeListeners (player) {
    player.removeEventListener('canplay', this.onReady)
    player.removeEventListener('play', this.onPlay)
    player.removeEventListener('waiting', this.onBuffer)
    player.removeEventListener('playing', this.onBufferEnd)
    player.removeEventListener('pause', this.onPause)
    player.removeEventListener('seeked', this.onSeek)
    player.removeEventListener('ended', this.onEnded)
    player.removeEventListener('error', this.onError)
    player.removeEventListener('enterpictureinpicture', this.onEnablePIP)
    player.removeEventListener('leavepictureinpicture', this.onDisablePIP)
    player.removeEventListener('webkitpresentationmodechanged', this.onPresentationModeChange)
  }

  // Proxy methods to prevent listener leaks
  onReady = (...args) => this.props.onReady(...args)
  onPlay = (...args) => this.props.onPlay(...args)
  onBuffer = (...args) => this.props.onBuffer(...args)
  onBufferEnd = (...args) => this.props.onBufferEnd(...args)
  onPause = (...args) => this.props.onPause(...args)
  onEnded = (...args) => this.props.onEnded(...args)
  onError = (...args) => this.props.onError(...args)
  onEnablePIP = (...args) => this.props.onEnablePIP(...args)

  onDisablePIP = e => {
    const { onDisablePIP, playing } = this.props
    onDisablePIP(e)
    if (playing) {
      this.play()
    }
  }

  onPresentationModeChange = e => {
    if (this.player && supportsWebKitPresentationMode(this.player)) {
      const { webkitPresentationMode } = this.player
      if (webkitPresentationMode === 'picture-in-picture') {
        this.onEnablePIP(e)
      } else if (webkitPresentationMode === 'inline') {
        this.onDisablePIP(e)
      }
    }
  }

  onSeek = e => {
    this.props.onSeek(e.target.currentTime)
  }

  shouldUseAudio (props) {
    if (props.config.forceVideo) {
      return false
    }
    if (props.config.attributes.poster) {
      return false // Use <video> so that poster is shown
    }
    return AUDIO_EXTENSIONS.test(props.url) || props.config.forceAudio
  }

  shouldUseHLS (url) {
    return (HLS_EXTENSIONS.test(url) && !IOS) || this.props.config.forceHLS
  }

  shouldUseDASH (url) {
    return DASH_EXTENSIONS.test(url) || this.props.config.forceDASH
  }

  load (url) {
    const { hlsVersion, hlsOptions, dashVersion } = this.props.config
    if (this.shouldUseHLS(url)) {
      getSDK(HLS_SDK_URL.replace('VERSION', hlsVersion), HLS_GLOBAL).then(Hls => {
        this.hls = new Hls(hlsOptions)
        this.hls.on(Hls.Events.ERROR, (e, data) => {
          this.props.onError(e, data, this.hls, Hls)
        })
        this.hls.loadSource(url)
        this.hls.attachMedia(this.player)
      })
    }
    if (this.shouldUseDASH(url)) {
      getSDK(DASH_SDK_URL.replace('VERSION', dashVersion), DASH_GLOBAL).then(dashjs => {
        this.dash = dashjs.MediaPlayer().create()
        this.dash.initialize(this.player, url, this.props.playing)
        this.dash.on('error', this.props.onError)
        this.dash.getDebug().setLogToBrowserConsole(false)
      })
    }

    if (url instanceof Array) {
      // When setting new urls (<source>) on an already loaded video,
      // HTMLMediaElement.load() is needed to reset the media element
      // and restart the media resource. Just replacing children source
      // dom nodes is not enough
      this.player.load()
    } else if (isMediaStream(url)) {
      try {
        this.player.srcObject = url
      } catch (e) {
        this.player.src = window.URL.createObjectURL(url)
      }
    }
  }

  play () {
    const promise = this.player.play()
    if (promise) {
      promise.catch(this.props.onError)
    }
  }

  pause () {
    this.player.pause()
  }

  stop () {
    this.player.removeAttribute('src')
    if (this.dash) {
      this.dash.reset()
    }
  }

  seekTo (seconds) {
    this.player.currentTime = seconds
  }

  setVolume (fraction) {
    this.player.volume = fraction
  }

  mute = () => {
    this.player.muted = true
  }

  unmute = () => {
    this.player.muted = false
  }

  enablePIP () {
    if (this.player.requestPictureInPicture && document.pictureInPictureElement !== this.player) {
      this.player.requestPictureInPicture()
    } else if (supportsWebKitPresentationMode(this.player) && this.player.webkitPresentationMode !== 'picture-in-picture') {
      this.player.webkitSetPresentationMode('picture-in-picture')
    }
  }

  disablePIP () {
    if (document.exitPictureInPicture && document.pictureInPictureElement === this.player) {
      document.exitPictureInPicture()
    } else if (supportsWebKitPresentationMode(this.player) && this.player.webkitPresentationMode !== 'inline') {
      this.player.webkitSetPresentationMode('inline')
    }
  }

  setPlaybackRate (rate) {
    this.player.playbackRate = rate
  }

  getDuration () {
    if (!this.player) return null
    const { duration, seekable } = this.player
    // on iOS, live streams return Infinity for the duration
    // so instead we use the end of the seekable timerange
    if (duration === Infinity && seekable.length > 0) {
      return seekable.end(seekable.length - 1)
    }
    return duration
  }

  getCurrentTime () {
    if (!this.player) return null
    return this.player.currentTime
  }

  getSecondsLoaded () {
    if (!this.player) return null
    const { buffered } = this.player
    if (buffered.length === 0) {
      return 0
    }
    const end = buffered.end(buffered.length - 1)
    const duration = this.getDuration()
    if (end > duration) {
      return duration
    }
    return end
  }

  getSource (url) {
    const useHLS = this.shouldUseHLS(url)
    const useDASH = this.shouldUseDASH(url)
    if (url instanceof Array || isMediaStream(url) || useHLS || useDASH) {
      return undefined
    }
    if (MATCH_DROPBOX_URL.test(url)) {
      return url.replace('www.dropbox.com', 'dl.dropboxusercontent.com')
    }
    return url
  }

  renderSourceElement = (source, index) => {
    if (typeof source === 'string') {
      return <source key={index} src={source} />
    }
    return <source key={index} {...source} />
  }

  renderTrack = (track, index) => {
    return <track key={index} {...track} />
  }

  ref = player => {
    if (this.player) {
      // Store previous player to be used by removeListeners()
      this.prevPlayer = this.player
    }
    this.player = player
  }

  render () {
    const { url, playing, loop, controls, muted, config, width, height } = this.props
    const useAudio = this.shouldUseAudio(this.props)
    const Element = useAudio ? 'audio' : 'video'
    const style = {
      width: width === 'auto' ? width : '100%',
      height: height === 'auto' ? height : '100%'
    }
    return (
      <Element
        ref={this.ref}
        src={this.getSource(url)}
        style={style}
        preload='auto'
        autoPlay={playing || undefined}
        controls={controls}
        muted={muted}
        loop={loop}
        {...config.attributes}
      >
        {url instanceof Array &&
          url.map(this.renderSourceElement)}
        {config.tracks.map(this.renderTrack)}
      </Element>
    )
  }
}
<commit_msg>Reset hls and dash before loading new url<commit_after>import React, { Component } from 'react'

import { getSDK, isMediaStream, supportsWebKitPresentationMode } from '../utils'
import { AUDIO_EXTENSIONS, HLS_EXTENSIONS, DASH_EXTENSIONS } from '../patterns'

const IOS = typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream
const HLS_SDK_URL = 'https://cdn.jsdelivr.net/npm/hls.js@VERSION/dist/hls.min.js'
const HLS_GLOBAL = 'Hls'
const DASH_SDK_URL = 'https://cdnjs.cloudflare.com/ajax/libs/dashjs/VERSION/dash.all.min.js'
const DASH_GLOBAL = 'dashjs'
const MATCH_DROPBOX_URL = /www\.dropbox\.com\/.+/

export default class FilePlayer extends Component {
  static displayName = 'FilePlayer'

  componentDidMount () {
    this.props.onMount && this.props.onMount(this)
    this.addListeners(this.player)
    if (IOS) {
      this.player.load()
    }
  }

  componentDidUpdate (prevProps) {
    if (this.shouldUseAudio(this.props) !== this.shouldUseAudio(prevProps)) {
      this.removeListeners(this.prevPlayer)
      this.addListeners(this.player)
    }
  }

  componentWillUnmount () {
    this.removeListeners(this.player)
    if (this.hls) {
      this.hls.destroy()
    }
  }

  addListeners (player) {
    const { playsinline } = this.props
    player.addEventListener('canplay', this.onReady)
    player.addEventListener('play', this.onPlay)
    player.addEventListener('waiting', this.onBuffer)
    player.addEventListener('playing', this.onBufferEnd)
    player.addEventListener('pause', this.onPause)
    player.addEventListener('seeked', this.onSeek)
    player.addEventListener('ended', this.onEnded)
    player.addEventListener('error', this.onError)
    player.addEventListener('enterpictureinpicture', this.onEnablePIP)
    player.addEventListener('leavepictureinpicture', this.onDisablePIP)
    player.addEventListener('webkitpresentationmodechanged', this.onPresentationModeChange)
    if (playsinline) {
      player.setAttribute('playsinline', '')
      player.setAttribute('webkit-playsinline', '')
      player.setAttribute('x5-playsinline', '')
    }
  }

  removeListeners (player) {
    player.removeEventListener('canplay', this.onReady)
    player.removeEventListener('play', this.onPlay)
    player.removeEventListener('waiting', this.onBuffer)
    player.removeEventListener('playing', this.onBufferEnd)
    player.removeEventListener('pause', this.onPause)
    player.removeEventListener('seeked', this.onSeek)
    player.removeEventListener('ended', this.onEnded)
    player.removeEventListener('error', this.onError)
    player.removeEventListener('enterpictureinpicture', this.onEnablePIP)
    player.removeEventListener('leavepictureinpicture', this.onDisablePIP)
    player.removeEventListener('webkitpresentationmodechanged', this.onPresentationModeChange)
  }

  // Proxy methods to prevent listener leaks
  onReady = (...args) => this.props.onReady(...args)
  onPlay = (...args) => this.props.onPlay(...args)
  onBuffer = (...args) => this.props.onBuffer(...args)
  onBufferEnd = (...args) => this.props.onBufferEnd(...args)
  onPause = (...args) => this.props.onPause(...args)
  onEnded = (...args) => this.props.onEnded(...args)
  onError = (...args) => this.props.onError(...args)
  onEnablePIP = (...args) => this.props.onEnablePIP(...args)

  onDisablePIP = e => {
    const { onDisablePIP, playing } = this.props
    onDisablePIP(e)
    if (playing) {
      this.play()
    }
  }

  onPresentationModeChange = e => {
    if (this.player && supportsWebKitPresentationMode(this.player)) {
      const { webkitPresentationMode } = this.player
      if (webkitPresentationMode === 'picture-in-picture') {
        this.onEnablePIP(e)
      } else if (webkitPresentationMode === 'inline') {
        this.onDisablePIP(e)
      }
    }
  }

  onSeek = e => {
    this.props.onSeek(e.target.currentTime)
  }

  shouldUseAudio (props) {
    if (props.config.forceVideo) {
      return false
    }
    if (props.config.attributes.poster) {
      return false // Use <video> so that poster is shown
    }
    return AUDIO_EXTENSIONS.test(props.url) || props.config.forceAudio
  }

  shouldUseHLS (url) {
    return (HLS_EXTENSIONS.test(url) && !IOS) || this.props.config.forceHLS
  }

  shouldUseDASH (url) {
    return DASH_EXTENSIONS.test(url) || this.props.config.forceDASH
  }

  load (url) {
    const { hlsVersion, hlsOptions, dashVersion } = this.props.config
    if (this.hls) {
      this.hls.destroy()
    }
    if (this.dash) {
      this.dash.reset()
    }
    if (this.shouldUseHLS(url)) {
      getSDK(HLS_SDK_URL.replace('VERSION', hlsVersion), HLS_GLOBAL).then(Hls => {
        this.hls = new Hls(hlsOptions)
        this.hls.on(Hls.Events.ERROR, (e, data) => {
          this.props.onError(e, data, this.hls, Hls)
        })
        this.hls.loadSource(url)
        this.hls.attachMedia(this.player)
      })
    }
    if (this.shouldUseDASH(url)) {
      getSDK(DASH_SDK_URL.replace('VERSION', dashVersion), DASH_GLOBAL).then(dashjs => {
        this.dash = dashjs.MediaPlayer().create()
        this.dash.initialize(this.player, url, this.props.playing)
        this.dash.on('error', this.props.onError)
        this.dash.getDebug().setLogToBrowserConsole(false)
      })
    }

    if (url instanceof Array) {
      // When setting new urls (<source>) on an already loaded video,
      // HTMLMediaElement.load() is needed to reset the media element
      // and restart the media resource. Just replacing children source
      // dom nodes is not enough
      this.player.load()
    } else if (isMediaStream(url)) {
      try {
        this.player.srcObject = url
      } catch (e) {
        this.player.src = window.URL.createObjectURL(url)
      }
    }
  }

  play () {
    const promise = this.player.play()
    if (promise) {
      promise.catch(this.props.onError)
    }
  }

  pause () {
    this.player.pause()
  }

  stop () {
    this.player.removeAttribute('src')
    if (this.dash) {
      this.dash.reset()
    }
  }

  seekTo (seconds) {
    this.player.currentTime = seconds
  }

  setVolume (fraction) {
    this.player.volume = fraction
  }

  mute = () => {
    this.player.muted = true
  }

  unmute = () => {
    this.player.muted = false
  }

  enablePIP () {
    if (this.player.requestPictureInPicture && document.pictureInPictureElement !== this.player) {
      this.player.requestPictureInPicture()
    } else if (supportsWebKitPresentationMode(this.player) && this.player.webkitPresentationMode !== 'picture-in-picture') {
      this.player.webkitSetPresentationMode('picture-in-picture')
    }
  }

  disablePIP () {
    if (document.exitPictureInPicture && document.pictureInPictureElement === this.player) {
      document.exitPictureInPicture()
    } else if (supportsWebKitPresentationMode(this.player) && this.player.webkitPresentationMode !== 'inline') {
      this.player.webkitSetPresentationMode('inline')
    }
  }

  setPlaybackRate (rate) {
    this.player.playbackRate = rate
  }

  getDuration () {
    if (!this.player) return null
    const { duration, seekable } = this.player
    // on iOS, live streams return Infinity for the duration
    // so instead we use the end of the seekable timerange
    if (duration === Infinity && seekable.length > 0) {
      return seekable.end(seekable.length - 1)
    }
    return duration
  }

  getCurrentTime () {
    if (!this.player) return null
    return this.player.currentTime
  }

  getSecondsLoaded () {
    if (!this.player) return null
    const { buffered } = this.player
    if (buffered.length === 0) {
      return 0
    }
    const end = buffered.end(buffered.length - 1)
    const duration = this.getDuration()
    if (end > duration) {
      return duration
    }
    return end
  }

  getSource (url) {
    const useHLS = this.shouldUseHLS(url)
    const useDASH = this.shouldUseDASH(url)
    if (url instanceof Array || isMediaStream(url) || useHLS || useDASH) {
      return undefined
    }
    if (MATCH_DROPBOX_URL.test(url)) {
      return url.replace('www.dropbox.com', 'dl.dropboxusercontent.com')
    }
    return url
  }

  renderSourceElement = (source, index) => {
    if (typeof source === 'string') {
      return <source key={index} src={source} />
    }
    return <source key={index} {...source} />
  }

  renderTrack = (track, index) => {
    return <track key={index} {...track} />
  }

  ref = player => {
    if (this.player) {
      // Store previous player to be used by removeListeners()
      this.prevPlayer = this.player
    }
    this.player = player
  }

  render () {
    const { url, playing, loop, controls, muted, config, width, height } = this.props
    const useAudio = this.shouldUseAudio(this.props)
    const Element = useAudio ? 'audio' : 'video'
    const style = {
      width: width === 'auto' ? width : '100%',
      height: height === 'auto' ? height : '100%'
    }
    return (
      <Element
        ref={this.ref}
        src={this.getSource(url)}
        style={style}
        preload='auto'
        autoPlay={playing || undefined}
        controls={controls}
        muted={muted}
        loop={loop}
        {...config.attributes}
      >
        {url instanceof Array &&
          url.map(this.renderSourceElement)}
        {config.tracks.map(this.renderTrack)}
      </Element>
    )
  }
}
<|endoftext|>


<commit_before>//所有服务器的配置参数
module.exports = {
    'rootPath': 'e:/Code/weibo/research/hb/'
};<commit_msg>ci<commit_after>//所有服务器的配置参数
module.exports = {
    'rootPath': '/usr/home/wukan/hb'
    // 'rootPath': 'e:/Code/weibo/research/hb/'
};<|endoftext|>