<commit_before>/*!
 * ${copyright}
 */

sap.ui.define([
	"sap/ui/Device",
	"sap/ui/fl/write/_internal/connectors/ObjectPathConnector",
	"sap/ui/fl/apply/_internal/connectors/ObjectStorageUtils"
], function(
	Device,
	ObjectPathConnector,
	ObjectStorageUtils
) {
	"use strict";

	var FakeLrepConnector = {};
	var FL_PREFIX = "sap.ui.fl";

	// prototype is used for overwriting methods (to stay compatible)
	FakeLrepConnector.prototype = {};

	/**
	 * Enables fake LRep connector.
	 *
	 * Hooks into the {@link sap.ui.fl.LrepConnector.createConnector} factory function to enable the fake LRep connector.
	 * After enabling fake LRep connector, function {@link sap.ui.fl.FakeLrepConnector.disableFakeConnector} must be called to restore the original connector.
	 *
	 * @param {string} sInitialComponentJsonPath Relative path to a test-component-changes.json file
	 */
	FakeLrepConnector.enableFakeConnector = function(sInitialComponentJsonPath) {
		this.setFlexibilityServicesAndClearCache("LocalStorageConnector", sInitialComponentJsonPath);
	};

	FakeLrepConnector.setFlexibilityServicesAndClearCache = function(sStorageConnectorName, sInitialComponentJsonPath) {
		this._oFlexibilityServices = sap.ui.getCore().getConfiguration().getFlexibilityServices();

		var aConnectorConfig = [];
		if (sInitialComponentJsonPath) {
			ObjectPathConnector.setJsonPath(sInitialComponentJsonPath);
			aConnectorConfig.push({connector: "ObjectPathConnector"});
		}
		aConnectorConfig.push({connector: sStorageConnectorName});
		sap.ui.getCore().getConfiguration().setFlexibilityServices(aConnectorConfig);
		sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();
	};

	/**
	 * Restores the original {@link sap.ui.fl.LrepConnector.createConnector} factory function.
	 */
	FakeLrepConnector.disableFakeConnector = function() {
		FakeLrepConnector.prototype = {};
		sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();

		// only reset the flexibility Services in case they were changes by the FakeConnector before
		if (this._oFlexibilityServices) {
			sap.ui.getCore().getConfiguration().setFlexibilityServices(this._oFlexibilityServices);
			delete this._oFlexibilityServices;
		}
	};

	FakeLrepConnector.forTesting = {
		getNumberOfChanges: function (oConnector, sReference) {
			return oConnector.loadFlexData({reference: sReference})
			.then(function (aResponses) {
				return aResponses.reduce(function (iNumberOfChanges, oResponse) {
					return iNumberOfChanges + oResponse.changes.length;
				}, 0);
			});
		},
		spyMethod: function (sandbox, assert, oConnector, sMethod) {
			var oSpy = sandbox.spy(oConnector, sMethod);

			return function (iNumberOfExpectedObjects, iCallIndex) {
				iCallIndex = iCallIndex || 0;
				var iNumberOfObjects = oSpy.getCall(iCallIndex).args[0].flexObjects.length;
				assert.equal(iNumberOfObjects, iNumberOfExpectedObjects, sMethod + " was called " + iNumberOfExpectedObjects + " times");
			};
		},
		clear: function(oConnector, mPropertyBag) {
			sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();
			return oConnector.reset(mPropertyBag);
		},
		setStorage: function(oConnector, oNewStorage) {
			oConnector.storage = oNewStorage;
		},
		synchronous: {
			clearAll: function (oStorage) {
				var fnRemoveItem = function(sKey) {
					var bIsFlexObject = sKey.includes(FL_PREFIX);

					if (!bIsFlexObject) {
						return;
					}

					oStorage.removeItem(sKey);
				};

				if (Device.browser.msie) {
					var iStorageItems = oStorage.length;
					for (var i = iStorageItems - 1; i >= 0; i--) {
						var sKey = oStorage.key(i);
						fnRemoveItem(sKey);
					}
				} else {
					Object.keys(oStorage).map(fnRemoveItem);
				}
			},
			store: function (oStorage, sKey, oItem) {
				var sFlexKey = ObjectStorageUtils.createFlexKey(sKey);
				var sItem = JSON.stringify(oItem);
				oStorage.setItem(sFlexKey, sItem);
			},
			getNumberOfChanges: function(oStorage, sReference) {
				var iCount = 0;
				Object.keys(oStorage).map(function(sKey) {
					var bIsFlexObject = sKey.includes(FL_PREFIX);

					if (!bIsFlexObject) {
						return;
					}
					var oFlexObject = JSON.parse(oStorage.getItem(sKey));
					if (oFlexObject.reference === sReference || oFlexObject.reference + ".Component" === sReference) {
						iCount++;
					}
				});
				return iCount;
			}
		}
	};

	return FakeLrepConnector;
}, true);<commit_msg>[INTERNAL] sap.ui.fl: IE de-support<commit_after>/*!
 * ${copyright}
 */

sap.ui.define([
	"sap/ui/fl/write/_internal/connectors/ObjectPathConnector",
	"sap/ui/fl/apply/_internal/connectors/ObjectStorageUtils"
], function(
	ObjectPathConnector,
	ObjectStorageUtils
) {
	"use strict";

	var FakeLrepConnector = {};
	var FL_PREFIX = "sap.ui.fl";

	// prototype is used for overwriting methods (to stay compatible)
	FakeLrepConnector.prototype = {};

	/**
	 * Enables fake LRep connector.
	 *
	 * Hooks into the {@link sap.ui.fl.LrepConnector.createConnector} factory function to enable the fake LRep connector.
	 * After enabling fake LRep connector, function {@link sap.ui.fl.FakeLrepConnector.disableFakeConnector} must be called to restore the original connector.
	 *
	 * @param {string} sInitialComponentJsonPath Relative path to a test-component-changes.json file
	 */
	FakeLrepConnector.enableFakeConnector = function(sInitialComponentJsonPath) {
		this.setFlexibilityServicesAndClearCache("LocalStorageConnector", sInitialComponentJsonPath);
	};

	FakeLrepConnector.setFlexibilityServicesAndClearCache = function(sStorageConnectorName, sInitialComponentJsonPath) {
		this._oFlexibilityServices = sap.ui.getCore().getConfiguration().getFlexibilityServices();

		var aConnectorConfig = [];
		if (sInitialComponentJsonPath) {
			ObjectPathConnector.setJsonPath(sInitialComponentJsonPath);
			aConnectorConfig.push({connector: "ObjectPathConnector"});
		}
		aConnectorConfig.push({connector: sStorageConnectorName});
		sap.ui.getCore().getConfiguration().setFlexibilityServices(aConnectorConfig);
		sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();
	};

	/**
	 * Restores the original {@link sap.ui.fl.LrepConnector.createConnector} factory function.
	 */
	FakeLrepConnector.disableFakeConnector = function() {
		FakeLrepConnector.prototype = {};
		sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();

		// only reset the flexibility Services in case they were changes by the FakeConnector before
		if (this._oFlexibilityServices) {
			sap.ui.getCore().getConfiguration().setFlexibilityServices(this._oFlexibilityServices);
			delete this._oFlexibilityServices;
		}
	};

	FakeLrepConnector.forTesting = {
		getNumberOfChanges: function (oConnector, sReference) {
			return oConnector.loadFlexData({reference: sReference})
			.then(function (aResponses) {
				return aResponses.reduce(function (iNumberOfChanges, oResponse) {
					return iNumberOfChanges + oResponse.changes.length;
				}, 0);
			});
		},
		spyMethod: function (sandbox, assert, oConnector, sMethod) {
			var oSpy = sandbox.spy(oConnector, sMethod);

			return function (iNumberOfExpectedObjects, iCallIndex) {
				iCallIndex = iCallIndex || 0;
				var iNumberOfObjects = oSpy.getCall(iCallIndex).args[0].flexObjects.length;
				assert.equal(iNumberOfObjects, iNumberOfExpectedObjects, sMethod + " was called " + iNumberOfExpectedObjects + " times");
			};
		},
		clear: function(oConnector, mPropertyBag) {
			sap.ui.requireSync("sap/ui/fl/Cache").clearEntries();
			return oConnector.reset(mPropertyBag);
		},
		setStorage: function(oConnector, oNewStorage) {
			oConnector.storage = oNewStorage;
		},
		synchronous: {
			clearAll: function (oStorage) {
				var fnRemoveItem = function(sKey) {
					var bIsFlexObject = sKey.includes(FL_PREFIX);

					if (!bIsFlexObject) {
						return;
					}

					oStorage.removeItem(sKey);
				};

				Object.keys(oStorage).map(fnRemoveItem);
			},
			store: function (oStorage, sKey, oItem) {
				var sFlexKey = ObjectStorageUtils.createFlexKey(sKey);
				var sItem = JSON.stringify(oItem);
				oStorage.setItem(sFlexKey, sItem);
			},
			getNumberOfChanges: function(oStorage, sReference) {
				var iCount = 0;
				Object.keys(oStorage).map(function(sKey) {
					var bIsFlexObject = sKey.includes(FL_PREFIX);

					if (!bIsFlexObject) {
						return;
					}
					var oFlexObject = JSON.parse(oStorage.getItem(sKey));
					if (oFlexObject.reference === sReference || oFlexObject.reference + ".Component" === sReference) {
						iCount++;
					}
				});
				return iCount;
			}
		}
	};

	return FakeLrepConnector;
}, true);<|endoftext|>


<commit_before>import React, { Component, PropTypes } from 'react';
import ChatArea from './components/ChatArea';
import ChatInput from './components/ChatInput';
import styles from './chat.scss';

export default class Chat extends Component {
  replay = (e) => {
    const name = e.currentTarget.textContent;
    const node = this.input.usermsg;
    node.value = name + ', ' + node.value;
    node.focus();
  };
  isMine = id => this.props.me.id === id;

  render() {
    const {
      messages, lang, onSend, onTranslate, withPhoto,
      onDelete, translateLanguages, nativeLng, onRestore, onBan } = this.props;
    return (

          <ChatArea messages={messages}
            replay={this.replay}
            isMine={this.isMine}
            onTranslate={onTranslate}
            onDelete={onDelete}
            onRestore={onRestore}
            onBan={onBan}
            lang={lang}
            translateLanguages={translateLanguages}
            nativeLng={nativeLng}
            withPhoto={withPhoto}
          />
          <ChatInput
            onSend={onSend}
            lang={lang}
            onTranslate={onTranslate}
            translateLanguages={translateLanguages}
            ref={node => {this.input = node;}}
          />

    );
  }
}

Chat.propTypes = {
  messages: PropTypes.array,
  onSend: PropTypes.func.isRequired,
  me: PropTypes.shape({
    id: PropTypes.string.isRequired,
    name: PropTypes.string.isRequired,
    avatar: PropTypes.string
  }).isRequired,
  lang: PropTypes.string,
  onTranslate: PropTypes.func,
  onDelete: PropTypes.func,
  onRestore: PropTypes.func,
  onBan: PropTypes.func,
  translateLanguages: PropTypes.array,
  nativeLng: PropTypes.string,
  withPhoto: PropTypes.bool
};

Chat.defaultProps = {
  messages: []
};<commit_msg>Remove unnecessary div<commit_after>import React, { Component, PropTypes } from 'react';
import ChatArea from './components/ChatArea';
import ChatInput from './components/ChatInput';
import styles from './chat.scss';

export default class Chat extends Component {
  replay = (e) => {
    const name = e.currentTarget.textContent;
    const node = this.input.usermsg;
    node.value = name + ', ' + node.value;
    node.focus();
  };
  isMine = id => this.props.me.id === id;

  render() {
    const {
      messages, lang, onSend, onTranslate, withPhoto,
      onDelete, translateLanguages, nativeLng, onRestore, onBan } = this.props;
    return (

        <ChatArea messages={messages}
          replay={this.replay}
          isMine={this.isMine}
          onTranslate={onTranslate}
          onDelete={onDelete}
          onRestore={onRestore}
          onBan={onBan}
          lang={lang}
          translateLanguages={translateLanguages}
          nativeLng={nativeLng}
          withPhoto={withPhoto}
        />
        <ChatInput
          onSend={onSend}
          lang={lang}
          onTranslate={onTranslate}
          translateLanguages={translateLanguages}
          ref={node => {this.input = node;}}
        />

    );
  }
}

Chat.propTypes = {
  messages: PropTypes.array,
  onSend: PropTypes.func.isRequired,
  me: PropTypes.shape({
    id: PropTypes.string.isRequired,
    name: PropTypes.string.isRequired,
    avatar: PropTypes.string
  }).isRequired,
  lang: PropTypes.string,
  onTranslate: PropTypes.func,
  onDelete: PropTypes.func,
  onRestore: PropTypes.func,
  onBan: PropTypes.func,
  translateLanguages: PropTypes.array,
  nativeLng: PropTypes.string,
  withPhoto: PropTypes.bool
};

Chat.defaultProps = {
  messages: []
};<|endoftext|>


<commit_before>// Build inverted index

var invertedIndex = {};

console.log("Constructing inverted index...");

Texts.find().forEach( function(doc) {
  var docId = doc._id;
  var text = doc.text;
  var docLength = doc.text.length;
  for (var i = 0; i < docLength - 2; i++) {
    var trigram = text.substring(i, i + 3);
    if (trigram in invertedIndex) {
      invertedIndex[trigram].push(docId);
    } else {
      invertedIndex[trigram] = [docId];
    }
  }
});

console.log("Found", Object.keys(invertedIndex).length, "trigrams in", Texts.find().count(), "docs.");

// Takes in query sent by client and narrows down number of docs in the inverted index to search.
processQuery = function(q) {
  // Array of values (other arrays) from the invertedIndex
  var i,
    j,
    subQueries = q["sub"],
    subQueryLen = subQueries.length,
    trigramList = q["trigram"],
    trigramListLen = trigramList.length,
    docIdLists = [],
    resultList;

  for (i = 0; i < subQueryLen; i++) {
    docIdLists.push(processQuery(subQueries[i]));
  }

  for (i = 0; i < trigramListLen; i++) {
    docIdLists.push(invertedIndex[trigramList[i]]);
    //console.log(docIdLists[docIdLists.length-1]);
  }

  switch (q["op"]) {
    case "AND":
      if (docIdLists.length === 0)
        break;
      resultList = docIdLists[0];

      // Iterate over remaining lists. If any elements
      // exist in them that aren't in the resultList,
      // remove the element from resultList.
      for (i = 0; i < docIdLists.length; i++) {
        var docIdList = docIdLists[i];
        for (j = 0; j < resultList.length; j++) {
          var docId = resultList[j];
          if (docIdList.indexOf(docId) < 0) {
            resultList.splice(j, 1);
          }
        }
      }
      break;

    case "OR":
      resultList = [];

      for (var docIdList in docIdLists) {
        for (var docId in docIdList) {
          if (docIdList.indexOf(docId) < 0) {
            resultList.push(docId);
          }
        }
      }
      break;

    case "ANY":
      throw "op NYI: \"ANY\"";
      break;

    case "ALL":
      throw "op NYI: \"ALL:\"";
      break;

    default:
      throw "Unrecognized op: " + q["op"];
  }

  console.log("About to return", typeof resultList, "which contains", typeof resultList[0]);
  console.log(JSON.stringify(q, null, 2));
  return resultList;
};<commit_msg>Log inverted index progress<commit_after>// Build inverted index

var invertedIndex = {};

console.log("Constructing inverted index...");

Texts.find().forEach( function(doc) {
  var docId = doc._id;
  var text = doc.text;
  var docLength = doc.text.length;
  for (var i = 0; i < docLength - 2; i++) {
    var trigram = text.substring(i, i + 3);
    if (trigram in invertedIndex) {
      invertedIndex[trigram].push(docId);
    } else {
      invertedIndex[trigram] = [docId];
    }
  }
  console.log("Processed doc. Trigrams: ", invertedIndex.length);
});

console.log("Found", Object.keys(invertedIndex).length, "trigrams in", Texts.find().count(), "docs.");

// Takes in query sent by client and narrows down number of docs in the inverted index to search.
processQuery = function(q) {
  // Array of values (other arrays) from the invertedIndex
  var i,
    j,
    subQueries = q["sub"],
    subQueryLen = subQueries.length,
    trigramList = q["trigram"],
    trigramListLen = trigramList.length,
    docIdLists = [],
    resultList;

  for (i = 0; i < subQueryLen; i++) {
    docIdLists.push(processQuery(subQueries[i]));
  }

  for (i = 0; i < trigramListLen; i++) {
    docIdLists.push(invertedIndex[trigramList[i]]);
    //console.log(docIdLists[docIdLists.length-1]);
  }

  switch (q["op"]) {
    case "AND":
      if (docIdLists.length === 0)
        break;
      resultList = docIdLists[0];

      // Iterate over remaining lists. If any elements
      // exist in them that aren't in the resultList,
      // remove the element from resultList.
      for (i = 0; i < docIdLists.length; i++) {
        var docIdList = docIdLists[i];
        for (j = 0; j < resultList.length; j++) {
          var docId = resultList[j];
          if (docIdList.indexOf(docId) < 0) {
            resultList.splice(j, 1);
          }
        }
      }
      break;

    case "OR":
      resultList = [];

      for (var docIdList in docIdLists) {
        for (var docId in docIdList) {
          if (docIdList.indexOf(docId) < 0) {
            resultList.push(docId);
          }
        }
      }
      break;

    case "ANY":
      throw "op NYI: \"ANY\"";
      break;

    case "ALL":
      throw "op NYI: \"ALL:\"";
      break;

    default:
      throw "Unrecognized op: " + q["op"];
  }

  console.log("About to return", typeof resultList, "which contains", typeof resultList[0]);
  console.log(JSON.stringify(q, null, 2));
  return resultList;
};<|endoftext|>


<commit_before>var app = require('app');
var dialog = require('dialog');
var fs = require('fs');
var path = require('path');
var Menu = require('menu');
var BrowserWindow = require('browser-window');

// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() {
  if (app.listeners('window-all-closed').length == 1)
    app.quit();
});

// Parse command line options.
var argv = process.argv.slice(1);
var option = { file: null, help: null, version: null, webdriver: null };
for (var i in argv) {
  if (argv[i] == '--version' || argv[i] == '-v') {
    option.version = true;
    break;
  } else if (argv[i] == '--help' || argv[i] == '-h') {
    option.help = true;
    break;
  } else if (argv[i] == '--test-type=webdriver') {
    option.webdriver = true;
  } else if (argv[i][0] == '-') {
    continue;
  } else {
    option.file = argv[i];
    break;
  }
}

// Create default menu.
app.once('ready', function() {
  var template;
  if (process.platform == 'darwin') {
    template = [
      {
        label: 'Electron',
        submenu: [
          {
            label: 'About Electron',
            selector: 'orderFrontStandardAboutPanel:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Services',
            submenu: []
          },
          {
            type: 'separator'
          },
          {
            label: 'Hide Electron',
            accelerator: 'Command+H',
            selector: 'hide:'
          },
          {
            label: 'Hide Others',
            accelerator: 'Command+Shift+H',
            selector: 'hideOtherApplications:'
          },
          {
            label: 'Show All',
            selector: 'unhideAllApplications:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Quit',
            accelerator: 'Command+Q',
            click: function() { app.quit(); }
          },
        ]
      },
      {
        label: 'Edit',
        submenu: [
          {
            label: 'Undo',
            accelerator: 'Command+Z',
            selector: 'undo:'
          },
          {
            label: 'Redo',
            accelerator: 'Shift+Command+Z',
            selector: 'redo:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Cut',
            accelerator: 'Command+X',
            selector: 'cut:'
          },
          {
            label: 'Copy',
            accelerator: 'Command+C',
            selector: 'copy:'
          },
          {
            label: 'Paste',
            accelerator: 'Command+V',
            selector: 'paste:'
          },
          {
            label: 'Select All',
            accelerator: 'Command+A',
            selector: 'selectAll:'
          },
        ]
      },
      {
        label: 'View',
        submenu: [
          {
            label: 'Reload',
            accelerator: 'Command+R',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.reload();
            }
          },
          {
            label: 'Toggle Full Screen',
            accelerator: 'Ctrl+Command+F',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          },
          {
            label: 'Toggle Developer Tools',
            accelerator: 'Alt+Command+I',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.toggleDevTools();
            }
          },
        ]
      },
      {
        label: 'Window',
        submenu: [
          {
            label: 'Minimize',
            accelerator: 'Command+M',
            selector: 'performMiniaturize:'
          },
          {
            label: 'Close',
            accelerator: 'Command+W',
            selector: 'performClose:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Bring All to Front',
            selector: 'arrangeInFront:'
          },
        ]
      },
      {
        label: 'Help',
        submenu: [
          {
            label: 'Learn More',
            click: function() { require('shell').openExternal('http://electron.atom.io') }
          },
          {
            label: 'Documentation',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
          },
          {
            label: 'Community Discussions',
            click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
          },
          {
            label: 'Search Issues',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
          }
        ]
      }
    ];
  } else {
    template = [
      {
        label: '&File',
        submenu: [
          {
            label: '&Open',
            accelerator: 'Ctrl+O',
          },
          {
            label: '&Close',
            accelerator: 'Ctrl+W',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.close();
            }
          },
        ]
      },
      {
        label: '&View',
        submenu: [
          {
            label: '&Reload',
            accelerator: 'Ctrl+R',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.reload();
            }
          },
          {
            label: 'Toggle &Full Screen',
            accelerator: 'F11',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          },
          {
            label: 'Toggle &Developer Tools',
            accelerator: 'Alt+Ctrl+I',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.toggleDevTools();
            }
          },
        ]
      },
      {
        label: 'Help',
        submenu: [
          {
            label: 'Learn More',
            click: function() { require('shell').openExternal('http://electron.atom.io') }
          },
          {
            label: 'Documentation',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
          },
          {
            label: 'Community Discussions',
            click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
          },
          {
            label: 'Search Issues',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
          }
        ]
      }
    ];
  }

  var menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
});

// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
  try {
    // Override app name and version.
    var packagePath = path.resolve(option.file);
    var packageJsonPath = path.join(packagePath, 'package.json');
    if (fs.existsSync(packageJsonPath)) {
      var packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
      if (packageJson.version)
        app.setVersion(packageJson.version);
      if (packageJson.productName)
        app.setName(packageJson.productName);
      else if (packageJson.name)
        app.setName(packageJson.name);
      app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
      app.setPath('userCache', path.join(app.getPath('cache'), app.getName()));
    }

    // Run the app.
    require('module')._load(packagePath, module, true);
  } catch(e) {
    if (e.code == 'MODULE_NOT_FOUND') {
      app.focus();
      dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString());
      process.exit(1);
    } else {
      console.error('App threw an error when running', e);
      throw e;
    }
  }
} else if (option.version) {
  console.log('v' + process.versions.electron);
  process.exit(0);
} else if (option.help) {
  var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n";
  helpMessage    += "Usage: electron [options] [path]\n\n";
  helpMessage    += "A path to an Electron application may be specified. The path must be to \n";
  helpMessage    += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
  helpMessage    += "Options:\n";
  helpMessage    += "  -h, --help            Print this usage message.\n";
  helpMessage    += "  -v, --version         Print the version.";
  console.log(helpMessage);
  process.exit(0);
} else {
  require('./default_app.js');
}
<commit_msg>Don't override user's menu in default_app<commit_after>var app = require('app');
var dialog = require('dialog');
var fs = require('fs');
var path = require('path');
var Menu = require('menu');
var BrowserWindow = require('browser-window');

// Quit when all windows are closed and no other one is listening to this.
app.on('window-all-closed', function() {
  if (app.listeners('window-all-closed').length == 1)
    app.quit();
});

// Parse command line options.
var argv = process.argv.slice(1);
var option = { file: null, help: null, version: null, webdriver: null };
for (var i in argv) {
  if (argv[i] == '--version' || argv[i] == '-v') {
    option.version = true;
    break;
  } else if (argv[i] == '--help' || argv[i] == '-h') {
    option.help = true;
    break;
  } else if (argv[i] == '--test-type=webdriver') {
    option.webdriver = true;
  } else if (argv[i][0] == '-') {
    continue;
  } else {
    option.file = argv[i];
    break;
  }
}

// Create default menu.
app.once('ready', function() {
  if (Menu.getApplicationMenu())
    return;

  var template;
  if (process.platform == 'darwin') {
    template = [
      {
        label: 'Electron',
        submenu: [
          {
            label: 'About Electron',
            selector: 'orderFrontStandardAboutPanel:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Services',
            submenu: []
          },
          {
            type: 'separator'
          },
          {
            label: 'Hide Electron',
            accelerator: 'Command+H',
            selector: 'hide:'
          },
          {
            label: 'Hide Others',
            accelerator: 'Command+Shift+H',
            selector: 'hideOtherApplications:'
          },
          {
            label: 'Show All',
            selector: 'unhideAllApplications:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Quit',
            accelerator: 'Command+Q',
            click: function() { app.quit(); }
          },
        ]
      },
      {
        label: 'Edit',
        submenu: [
          {
            label: 'Undo',
            accelerator: 'Command+Z',
            selector: 'undo:'
          },
          {
            label: 'Redo',
            accelerator: 'Shift+Command+Z',
            selector: 'redo:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Cut',
            accelerator: 'Command+X',
            selector: 'cut:'
          },
          {
            label: 'Copy',
            accelerator: 'Command+C',
            selector: 'copy:'
          },
          {
            label: 'Paste',
            accelerator: 'Command+V',
            selector: 'paste:'
          },
          {
            label: 'Select All',
            accelerator: 'Command+A',
            selector: 'selectAll:'
          },
        ]
      },
      {
        label: 'View',
        submenu: [
          {
            label: 'Reload',
            accelerator: 'Command+R',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.reload();
            }
          },
          {
            label: 'Toggle Full Screen',
            accelerator: 'Ctrl+Command+F',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          },
          {
            label: 'Toggle Developer Tools',
            accelerator: 'Alt+Command+I',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.toggleDevTools();
            }
          },
        ]
      },
      {
        label: 'Window',
        submenu: [
          {
            label: 'Minimize',
            accelerator: 'Command+M',
            selector: 'performMiniaturize:'
          },
          {
            label: 'Close',
            accelerator: 'Command+W',
            selector: 'performClose:'
          },
          {
            type: 'separator'
          },
          {
            label: 'Bring All to Front',
            selector: 'arrangeInFront:'
          },
        ]
      },
      {
        label: 'Help',
        submenu: [
          {
            label: 'Learn More',
            click: function() { require('shell').openExternal('http://electron.atom.io') }
          },
          {
            label: 'Documentation',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
          },
          {
            label: 'Community Discussions',
            click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
          },
          {
            label: 'Search Issues',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
          }
        ]
      }
    ];
  } else {
    template = [
      {
        label: '&File',
        submenu: [
          {
            label: '&Open',
            accelerator: 'Ctrl+O',
          },
          {
            label: '&Close',
            accelerator: 'Ctrl+W',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.close();
            }
          },
        ]
      },
      {
        label: '&View',
        submenu: [
          {
            label: '&Reload',
            accelerator: 'Ctrl+R',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.reload();
            }
          },
          {
            label: 'Toggle &Full Screen',
            accelerator: 'F11',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          },
          {
            label: 'Toggle &Developer Tools',
            accelerator: 'Alt+Ctrl+I',
            click: function() {
              var focusedWindow = BrowserWindow.getFocusedWindow();
              if (focusedWindow)
                focusedWindow.toggleDevTools();
            }
          },
        ]
      },
      {
        label: 'Help',
        submenu: [
          {
            label: 'Learn More',
            click: function() { require('shell').openExternal('http://electron.atom.io') }
          },
          {
            label: 'Documentation',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/tree/master/docs#readme') }
          },
          {
            label: 'Community Discussions',
            click: function() { require('shell').openExternal('https://discuss.atom.io/c/electron') }
          },
          {
            label: 'Search Issues',
            click: function() { require('shell').openExternal('https://github.com/atom/electron/issues') }
          }
        ]
      }
    ];
  }

  var menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
});

// Start the specified app if there is one specified in command line, otherwise
// start the default app.
if (option.file && !option.webdriver) {
  try {
    // Override app name and version.
    var packagePath = path.resolve(option.file);
    var packageJsonPath = path.join(packagePath, 'package.json');
    if (fs.existsSync(packageJsonPath)) {
      var packageJson = JSON.parse(fs.readFileSync(packageJsonPath));
      if (packageJson.version)
        app.setVersion(packageJson.version);
      if (packageJson.productName)
        app.setName(packageJson.productName);
      else if (packageJson.name)
        app.setName(packageJson.name);
      app.setPath('userData', path.join(app.getPath('appData'), app.getName()));
      app.setPath('userCache', path.join(app.getPath('cache'), app.getName()));
    }

    // Run the app.
    require('module')._load(packagePath, module, true);
  } catch(e) {
    if (e.code == 'MODULE_NOT_FOUND') {
      app.focus();
      dialog.showErrorBox('Error opening app', 'The app provided is not a valid electron app, please read the docs on how to write one:\nhttps://github.com/atom/electron/tree/master/docs\n\n' + e.toString());
      process.exit(1);
    } else {
      console.error('App threw an error when running', e);
      throw e;
    }
  }
} else if (option.version) {
  console.log('v' + process.versions.electron);
  process.exit(0);
} else if (option.help) {
  var helpMessage = "Electron v" + process.versions.electron + " - Cross Platform Desktop Application Shell\n\n";
  helpMessage    += "Usage: electron [options] [path]\n\n";
  helpMessage    += "A path to an Electron application may be specified. The path must be to \n";
  helpMessage    += "an index.js file or to a folder containing a package.json or index.js file.\n\n";
  helpMessage    += "Options:\n";
  helpMessage    += "  -h, --help            Print this usage message.\n";
  helpMessage    += "  -v, --version         Print the version.";
  console.log(helpMessage);
  process.exit(0);
} else {
  require('./default_app.js');
}
<|endoftext|>


<commit_before>/* global fetch */
/* global cozy */
import { Component } from 'preact'

import * as accounts from './accounts'
import * as konnectors from './konnectors'

const INSTALL_TIMEOUT = 120
const KONNECTOR_STATE_READY = 'ready'

export default class MyAccountsStore {
  constructor (connectors, folders, context) {
    this.listener = null
    this.connectors = connectors
    this.folders = folders
    this.useCases = require(`../contexts/${context}/index`).useCases
  }

  subscribeTo (connectorId, listener) {
    this.listener = listener
    return this.find(c => c.id === connectorId)
  }

  unsubscribe () {
    this.listener = null
  }

  updateConnector (connector) {
    if (connector) {
      this.connectors = this.connectors.map(
        c => c.slug === connector.slug ? Object.assign({}, c, connector) : c
      )
      if (this.listener) {
        this.listener(this.find(c => c.slug === connector.slug))
      }
    }
    return this.connectors.find(k => k.slug === connector.slug)
  }

  getCategories () {
    return this.connectors.map(a => a.category).filter((cat, idx, all) => all.indexOf(cat) === idx)
  }

  getUseCases () {
    return this.useCases
  }

  find (cb) {
    return this.connectors.find(cb)
  }

  findConnected () {
    return this.connectors.filter(c => c.accounts.length !== 0)
  }

  findByCategory ({filter}) {
    return filter === 'all' ? this.connectors
      : this.connectors.filter(c => c.category === filter)
  }

  findByUseCase (slug) {
    let useCase = this.useCases.find(u => u.slug === slug)
    return useCase.connectors.map(c1 => this.find(c2 => c1.slug === c2.slug))
  }

  getKonnectorFolder (konnector, base = '/') {
    base = base.charAt(base.length) === '/'
      ? base.substr(0, base.length - 1)
        : base

    base = base.charAt(0) === '/'
      ? base
        : `/${base}`

    const folderPath = `${base}/${konnector.name}`
    return cozy.client.files.createDirectoryByPath(folderPath)
  }

  connectAccount (konnector, account, folder) {
    const result = account.id
      // TODO: replace by updateAccount
      ? Promise.resolve(account)
        : this.addAccount(konnector, account.values)
    result
    // .then(account => {
    //   // TODO waiting for the back to return the permission document after konnector installation
    //   return cozy.client.fetchJSON('PATCH', `/permissions/${konnector.links.permissions}`, {
    //     data: {
    //       id: konnector.links.permissions,
    //       type: 'io.cozy.permissions',
    //       permissions: {
    //         'add-this': {
    //           type: 'io.cozy.files',
    //           values: [folder._id]
    //         }
    //       }
    //     }
    //   })
    //   .then(() => account)
    // })
    // .then(account => {
    //   // TODO waiting for the back to allow folders to be referenced
    //   return cozy.client.fetchJSON('POST', `/files/${folder._id}/relationships/referenced_by`, {
    //     data: {
    //       type: 'io.cozy.konnectors',
    //       id: konnector._id
    //     }
    //   })
    //   .then(() => account)
    // })
    .then(account => {
      // now try to run the connector one time
      return konnectors.run(cozy.client, konnector.slug, account._id, folder._id)
    })
    return result
  }

  isInstalled (konnector) {
    return konnector.state && konnector.state === KONNECTOR_STATE_READY
  }

  addAccount (konnector, auth) {
    return accounts.create(cozy.client, konnector, auth)
      .then(account => {
        const installationPromise = this.isInstalled(konnector)
          ? Promise.resolve(konnector)
            : konnectors.install(cozy.client, konnector.slug, konnector.repo, INSTALL_TIMEOUT * 1000)

        return installationPromise
          .then(konnector => {
            return konnectors.addAccount(cozy.client, konnector, account)
          })
      })
  }

  fetchAccounts (accountType, index) {
    if (!index && this.accountsIndex) index = this.accountsIndex
    return accounts.getAccountsByType(cozy.client, accountType, index)
  }

  updateAccount (connectorId, accountIdx, values) {
    let connector = this.find(c => c.id === connectorId)
    connector.accounts[accountIdx] = values
    return this.putConnector(connector)
  }

  synchronize (connectorId) {
    let connector = this.find(c => c.id === connectorId)
    return this.importConnector(connector)
      .then(() => this.startConnectorPoll(connector.id))
  }

  deleteAccount (connectorId, accountIdx) {
    let connector = this.find(c => c.id === connectorId)
    connector.accounts.splice(accountIdx, 1)
    return this.importConnector(connector)
      .then(() => this.updateConnector(connector))
  }

  manifestToKonnector (manifest) {
    return manifest
  }

  // get properties from installed konnector or remote manifest
  fetchKonnectorInfos (slug) {
    return this.getInstalledConnector(slug)
      .then(konnector => {
        if (!konnector) {
          konnector = this.connectors.find(k => k.slug === slug)
        }

        return konnector ? konnectors.fetchManifest(cozy.client, konnector.repo)
          .then(this.manifestToKonnector)
          .catch(error => {
            console.warn && console.warn(`Cannot fetch konnector's manifest (Error ${error.status})`)
            return konnector
          }) : null
      })
      .then(konnector => konnector ? this.updateConnector(konnector) : null)
  }

  getInstalledConnector (slug) {
    return konnectors.findBySlug(cozy.client, slug)
  }

  putConnector (connector) {
    return this.fetch('PUT', `konnectors/${connector.id}`, connector)
      .then(response => {
        return response.status === 200
          ? response.text()
          : Promise.reject(response)
      })
      .then((body) => {
        let connector = JSON.parse(body)
        this.updateConnector(connector)
        return connector
      })
  }

  importConnector (connector) {
    return this.fetch('POST', `konnectors/${connector.id}/import`, connector)
      .then(response => {
        return response.status === 200
          ? response
          : Promise.reject(response)
      })
  }

  startConnectorPoll (connectorId, timeout = 30000, interval = 500) {
    let endTime = Number(new Date()) + timeout

    let checkCondition = function (resolve, reject) {
      return this.fetch('GET', `konnectors/${connectorId}`)
        .then(response => response.text()).then(body => {
          let connector = JSON.parse(body)
          if (!connector.isImporting) {
            this.updateConnector(connector)
            resolve(connector)
          } else if (Number(new Date()) < endTime) {
            setTimeout(checkCondition, interval, resolve, reject)
          } else {
            this.updateConnector(connector)
            reject(new Error('polling timed out'))
          }
        })
    }.bind(this)
    return new Promise((resolve, reject) => {
      setTimeout(checkCondition, 500, resolve, reject)
    })
  }

  refreshFolders () {
    return this.fetch('GET', 'folders')
      .then(response => response.text()).then(body => {
        this.folders = JSON.parse(body)
        Promise.resolve()
      })
  }

  fetch (method, url, body) {
    const STACK_DOMAIN = '//' + document.querySelector('[role=application]').dataset.cozyDomain
    const STACK_TOKEN = document.querySelector('[role=application]').dataset.cozyToken
    let params = {
      method: method,
      credentials: 'include',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${STACK_TOKEN}`
      }
    }
    if (body) {
      params.body = JSON.stringify(body)
    }
    return fetch(`${STACK_DOMAIN}${url}`, params)
      .then(response => {
        let data
        const contentType = response.headers.get('content-type')
        if (contentType && contentType.indexOf('json') >= 0) {
          data = response.json()
        } else {
          data = response.text()
        }

        return (response.status === 200 || response.status === 202 || response.status === 204)
          ? data
          : data.then(Promise.reject.bind(Promise))
      })
  }

  createIntentService (intent, window) {
    return cozy.client.intents.createService(intent, window)
  }
}

export class Provider extends Component {
  getChildContext () {
    return { store: this.store }
  }

  constructor (props, context) {
    super(props, context)
    this.store = props.store
  }

  render ({children}) {
    return (children && children[0]) || null
  }
}
<commit_msg>fix: removed commented permissions and folder association commands<commit_after>/* global fetch */
/* global cozy */
import { Component } from 'preact'

import * as accounts from './accounts'
import * as konnectors from './konnectors'

const INSTALL_TIMEOUT = 120
const KONNECTOR_STATE_READY = 'ready'

export default class MyAccountsStore {
  constructor (connectors, folders, context) {
    this.listener = null
    this.connectors = connectors
    this.folders = folders
    this.useCases = require(`../contexts/${context}/index`).useCases
  }

  subscribeTo (connectorId, listener) {
    this.listener = listener
    return this.find(c => c.id === connectorId)
  }

  unsubscribe () {
    this.listener = null
  }

  updateConnector (connector) {
    if (connector) {
      this.connectors = this.connectors.map(
        c => c.slug === connector.slug ? Object.assign({}, c, connector) : c
      )
      if (this.listener) {
        this.listener(this.find(c => c.slug === connector.slug))
      }
    }
    return this.connectors.find(k => k.slug === connector.slug)
  }

  getCategories () {
    return this.connectors.map(a => a.category).filter((cat, idx, all) => all.indexOf(cat) === idx)
  }

  getUseCases () {
    return this.useCases
  }

  find (cb) {
    return this.connectors.find(cb)
  }

  findConnected () {
    return this.connectors.filter(c => c.accounts.length !== 0)
  }

  findByCategory ({filter}) {
    return filter === 'all' ? this.connectors
      : this.connectors.filter(c => c.category === filter)
  }

  findByUseCase (slug) {
    let useCase = this.useCases.find(u => u.slug === slug)
    return useCase.connectors.map(c1 => this.find(c2 => c1.slug === c2.slug))
  }

  getKonnectorFolder (konnector, base = '/') {
    base = base.charAt(base.length) === '/'
      ? base.substr(0, base.length - 1)
        : base

    base = base.charAt(0) === '/'
      ? base
        : `/${base}`

    const folderPath = `${base}/${konnector.name}`
    return cozy.client.files.createDirectoryByPath(folderPath)
  }

  connectAccount (konnector, account, folder) {
    const result = account.id
      // TODO: replace by updateAccount
      ? Promise.resolve(account)
        : this.addAccount(konnector, account.values)
    result
    .then(account => {
      // now try to run the connector one time
      return konnectors.run(cozy.client, konnector.slug, account._id, folder._id)
    })
    return result
  }

  isInstalled (konnector) {
    return konnector.state && konnector.state === KONNECTOR_STATE_READY
  }

  addAccount (konnector, auth) {
    return accounts.create(cozy.client, konnector, auth)
      .then(account => {
        const installationPromise = this.isInstalled(konnector)
          ? Promise.resolve(konnector)
            : konnectors.install(cozy.client, konnector.slug, konnector.repo, INSTALL_TIMEOUT * 1000)

        return installationPromise
          .then(konnector => {
            return konnectors.addAccount(cozy.client, konnector, account)
          })
      })
  }

  fetchAccounts (accountType, index) {
    if (!index && this.accountsIndex) index = this.accountsIndex
    return accounts.getAccountsByType(cozy.client, accountType, index)
  }

  updateAccount (connectorId, accountIdx, values) {
    let connector = this.find(c => c.id === connectorId)
    connector.accounts[accountIdx] = values
    return this.putConnector(connector)
  }

  synchronize (connectorId) {
    let connector = this.find(c => c.id === connectorId)
    return this.importConnector(connector)
      .then(() => this.startConnectorPoll(connector.id))
  }

  deleteAccount (connectorId, accountIdx) {
    let connector = this.find(c => c.id === connectorId)
    connector.accounts.splice(accountIdx, 1)
    return this.importConnector(connector)
      .then(() => this.updateConnector(connector))
  }

  manifestToKonnector (manifest) {
    return manifest
  }

  // get properties from installed konnector or remote manifest
  fetchKonnectorInfos (slug) {
    return this.getInstalledConnector(slug)
      .then(konnector => {
        if (!konnector) {
          konnector = this.connectors.find(k => k.slug === slug)
        }

        return konnector ? konnectors.fetchManifest(cozy.client, konnector.repo)
          .then(this.manifestToKonnector)
          .catch(error => {
            console.warn && console.warn(`Cannot fetch konnector's manifest (Error ${error.status})`)
            return konnector
          }) : null
      })
      .then(konnector => konnector ? this.updateConnector(konnector) : null)
  }

  getInstalledConnector (slug) {
    return konnectors.findBySlug(cozy.client, slug)
  }

  putConnector (connector) {
    return this.fetch('PUT', `konnectors/${connector.id}`, connector)
      .then(response => {
        return response.status === 200
          ? response.text()
          : Promise.reject(response)
      })
      .then((body) => {
        let connector = JSON.parse(body)
        this.updateConnector(connector)
        return connector
      })
  }

  importConnector (connector) {
    return this.fetch('POST', `konnectors/${connector.id}/import`, connector)
      .then(response => {
        return response.status === 200
          ? response
          : Promise.reject(response)
      })
  }

  startConnectorPoll (connectorId, timeout = 30000, interval = 500) {
    let endTime = Number(new Date()) + timeout

    let checkCondition = function (resolve, reject) {
      return this.fetch('GET', `konnectors/${connectorId}`)
        .then(response => response.text()).then(body => {
          let connector = JSON.parse(body)
          if (!connector.isImporting) {
            this.updateConnector(connector)
            resolve(connector)
          } else if (Number(new Date()) < endTime) {
            setTimeout(checkCondition, interval, resolve, reject)
          } else {
            this.updateConnector(connector)
            reject(new Error('polling timed out'))
          }
        })
    }.bind(this)
    return new Promise((resolve, reject) => {
      setTimeout(checkCondition, 500, resolve, reject)
    })
  }

  refreshFolders () {
    return this.fetch('GET', 'folders')
      .then(response => response.text()).then(body => {
        this.folders = JSON.parse(body)
        Promise.resolve()
      })
  }

  fetch (method, url, body) {
    const STACK_DOMAIN = '//' + document.querySelector('[role=application]').dataset.cozyDomain
    const STACK_TOKEN = document.querySelector('[role=application]').dataset.cozyToken
    let params = {
      method: method,
      credentials: 'include',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
        'Authorization': `Bearer ${STACK_TOKEN}`
      }
    }
    if (body) {
      params.body = JSON.stringify(body)
    }
    return fetch(`${STACK_DOMAIN}${url}`, params)
      .then(response => {
        let data
        const contentType = response.headers.get('content-type')
        if (contentType && contentType.indexOf('json') >= 0) {
          data = response.json()
        } else {
          data = response.text()
        }

        return (response.status === 200 || response.status === 202 || response.status === 204)
          ? data
          : data.then(Promise.reject.bind(Promise))
      })
  }

  createIntentService (intent, window) {
    return cozy.client.intents.createService(intent, window)
  }
}

export class Provider extends Component {
  getChildContext () {
    return { store: this.store }
  }

  constructor (props, context) {
    super(props, context)
    this.store = props.store
  }

  render ({children}) {
    return (children && children[0]) || null
  }
}
<|endoftext|>


<commit_before>var io = io.connect(),
    twats = [];

var template = '
'+
'
'+
'<%= text %>'+
'

'+
'<%= date %>'+
'

';

var maker = _.template(template);

$('#submit').click(function () {
  var hand = $('#handle').val();
  if (!hand) {
    alert('Please enter a twitter handle.');
  }
  io.emit('handle', { handle: hand });
});

io.on('twoots', function (twoots) {
  $('#twoots').html(' ');
  twats = jumble(twoots);
  console.log(twats);
  twats = _.map(twats, function (tweet) {
    return { text: tweet, date: new Date() };
  });
  for (var tw in twats) {
    $('#twoots').append(maker(twats[tw]));
  }
});

$("#handle").keyup(function(event){
    if(event.keyCode == 13){
      $("#submit").click();
    }
});

function jumble (tweets) {
  var words = [],
    newTweets = [];
  _.map(tweets, function (tweet) {
    words = _.union(words, (tweet.text).split(' '));
  });
  nextWord = 7;
  for (var i = 0; i <= 20; i++) {
    var newTweet = '';
    var tweetLen = Math.floor(Math.random()*140);
    while (newTweet.length < tweetLen) {
      var index = Math.floor(Math.random()*words.length);
      newTweet += words[index] + ' ';
      while (words[index].length < 5) {
        index++;
        newTweet += words[index] + ' ';
      }
    }
    newTweets.push(newTweet);
  }
  return newTweets;
}<commit_msg>Replaced union statement with concat to keep duplicate words<commit_after>var io = io.connect(),
    twats = [];

var template = '
'+
'
'+
'<%= text %>'+
'

'+
'<%= date %>'+
'

';

var maker = _.template(template);

$('#submit').click(function () {
  var hand = $('#handle').val();
  if (!hand) {
    alert('Please enter a twitter handle.');
    return null;
  } else if (hand[0] == '@') {
    hand = hand.substring(1);
  }
  io.emit('handle', { handle: hand });
});

io.on('twoots', function (twoots) {
  $('#twoots').html(' ');
  twats = jumble(twoots);
  twats = _.map(twats, function (tweet) {
    return { text: tweet, date: new Date() };
  });
  for (var tw in twats) {
    $('#twoots').append(maker(twats[tw]));
  }
});

$("#handle").keyup(function(event){
    if(event.keyCode == 13){
      $("#submit").click();
    }
});

function jumble (tweets) {
  var words = [],
    newTweets = [];
  _.map(tweets, function (tweet) {
    words = words.concat(tweet.text.split(' '));
  });
  nextWord = 7;
  for (var i = 0; i <= 20; i++) {
    var newTweet = '';
    var tweetLen = Math.floor(Math.random()*140);
    while (newTweet.length < tweetLen) {
      var index = Math.floor(Math.random()*words.length);
      if (words[index].substring(0,4) != 'http') {
        newTweet += words[index] + ' ';
      }
      while (words[index].length < 5) {
        index++;
        if (words[index].substring(0,4) != 'http') {
          newTweet += words[index] + ' ';
        }
      }
    }
    newTweets.push(newTweet);
  }
  return newTweets;
}<|endoftext|>


<commit_before>/** ****************************************************************************
*   @license                                                                   *
*   Copyright 2017 random-parts. All Rights Reserved.                          *
*                                                                              *
*   Licensed under the Apache License, Version 2.0 (the "License");            *
*   you may not use this file except in compliance with the License.           *
*   You may obtain a copy of the License at                                    *
*                                                                              *
*       http://www.apache.org/licenses/LICENSE-2.0                             *
*                                                                              *
*   Unless required by applicable law or agreed to in writing, software        *
*   distributed under the License is distributed on an "AS IS" BASIS,          *
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
*   See the License for the specific language governing permissions and        *
*   limitations under the License.                                             *
***************************************************************************** */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*       _____               ___               _      ___  _____   _____        *
*      |_   _|__ __ _ _ __ / __|_ __  ___ _ _| |_ __| _ \/ __\ \ / / _ \       *
*        | |/ -_) _` | '  \\__ \ '_ \/ _ \ '_|  _(_-<   /\__ \\ V /|  _/       *
*        |_|\___\__,_|_|_|_|___/ .__/\___/_|  \__/__/_|_\|___/ \_/ |_|         *
*                              |_|                                             *
*                                                                              *
*        Team Sports RSVP - Team schedule management spreadsheet add-on        *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**
 * @file Contains the controller methods used to orchestrate script actions
 * @license Apache License, Version 2.0
 * @version 1.1.9
 */

/**
 * ---
 * Script Configuration Object for debugging. Sets the proper Spreadsheeet Object
 * depending on if the script is run as an add-on[!debug]
 * or from the script-editor[debug]
 *
 * @namespace Config
 * @property {Boolean} debug
 * @property {String} debug_ss_id - spreadsheet id for testing
 * @property {Spreadsheet} spreadsheet - `debug:` SpreadsheetByID()

 * `!debug:` ActiveSpreadsheet()
 * @property {Form} team_form - `debug:` openByUrl()
 `!debug:` getActiveForm()
 */
var Config = {
  debug: false,
  debug_ss_id: "SHEET_ID",
  spreadsheet: function () {
    if (this.debug) { return SpreadsheetApp.openById(this.debug_ss_id) }
     else { return SpreadsheetApp.getActiveSpreadsheet() }
  },
  team_form: function () {
      var form_url = this.spreadsheet().getFormUrl();
      return (form_url != null) ? FormApp.openByUrl(form_url) : null;
  }
}

/**
 * ---
 * onInstall() event that runs once. Runs the first time the add-on is installed.
 * It sets-up the triggers then runs onOpen to build the menu.
 *
 * @param {EventObject} e
 */
function onInstall (e) {
  // Install the script project triggers
  onUpdateTriggers();

  // Run to get the Add-on Menu
  onOpen(e);
}

/**
 * ---
 * onOpen() event runs the start-up processes, i.e add-on menu build,
 * when the speadsheet is opened.
 *
 * @param {EventObject} e
 */
function onOpen (e) {
  var ss = Config.spreadsheet();
  // Build the Add-On Menu
  ui().menu(e);
  SpreadsheetApp.flush();

  ss.setActiveSheet(ss.getSheets()[0]);
}

/**
 * ---
 * Auto runs the daily tasks. Set to update the schedule and then
 * process any emails that should go out for the day.
 */
function onDailyTrigger () {
  // Update the form confirmation message
  formService().updateConfirmation();

  // Update the displayed schedule
  scheduleService().update();

  // Check if emails should be sent; if so check that there is a form to send; send
  if (emailService().isEmailDay()) {
    var ss = Config.spreadsheet();
     if (ss.getFormUrl() == null) { onCreateForm() }

    emailService().sendMail();
  }
}

/**
 * ---
 * Form submit event triggers the app to update the displayed season schedule
 *
 * @param {EventObject} e
 */
function onFormSubmit (e) {
  formService().handleResponse(e);
}

/**
 * ---
 * Sheet edit event within the web schedule range triggers an update to
 * the displayed schedule when it pull changes in the schedule from the website
 *
 * @requires Installed onEdit() Trigger
 * @param {EventObject} e
 */
function onSheetEdit (e) {
  var ss = e.source;
  var range = e.range;
  var change_cell_row = e.range.rowStart;
  var change_cell_col = e.range.columnStart;
  var data_range = ss.getRangeByName("webSchedule");

  // Check if the edits are with the web data/schedule values
  if ((data_range.getRow() <= change_cell_row == change_cell_row <= data_range.getLastRow()) &&
      (data_range.getColumn() <= change_cell_col == change_cell_col <= data_range.getLastColumn())) {
    // Run the schedule update
    scheduleService().update();
  }
}

/**
 * ---
 * Creates the sheet(s) needed to run a new season. Can be run from the
 * Add-on Menu.
 *
 */
function onNewSeason () {
  var ss = Config.spreadsheet();
  var sheet_name = ui().prompt.sheetname;
  var ss_triggers = ScriptApp.getUserTriggers(ss);
  var active_sheet;
   // Install add-on triggers for this spreadsheet
   if (ss_triggers.length == 0) { onUpdateTriggers() }
   // Create a template sheet if one does not exist
   if (template(ss).getTemplate() == null) { sheetService().create.template() }

  // Create a season sheet
  sheetService().create.season(sheet_name);
  // Give it time to do what it needs to do
  Utilities.sleep(250);

  // Set the new sheet as the ActiveSheet
  active_sheet = ss.getSheets()[0];
  active_sheet.showSheet();
  ss.setActiveSheet(active_sheet);

  SpreadsheetApp.flush();
  Utilities.sleep(250);

  // Copy the returning squad mates to the new season sheet
  teamService().squad.setReturning();

  SpreadsheetApp.flush();
  Utilities.sleep(250);

  // Set the new web/online schedule link & team name
  onWeblinkUpdate();

  // Create a team form if one is not attached
  if (ss.getFormUrl() == null) { onCreateForm() }

  // Set the sheet edit protection & data validation
  sheetService().update.protection();
  sheetService().update.validation();

  // Let the user know the set-up is finished
  ui().alert.done();
}

/*******************************************************************************
*                       Menu Options - Advanced Features                       *
*******************************************************************************/

/**
 * --- Menu Option: "Extra Options Help" */
function onOptionsHelp () { ui().modal.optionsHelp() }

/**
 * --- Menu Option: "Re-install Triggers" */
function onUpdateTriggers () { utils().script.install.triggers() }

/**
 * --- Menu Option: "Remove Triggers" */
function onRemoveTriggers () { utils().script.clean.triggers() }

/**
 * --- Menu Option: "Remove Conditional Formatting" */
function onRemoveCondFormatting () { sheetService().clear.conditionalFormatting() }

/**
 * --- Menu Option: "Remove Dependencies [soft un-install]" */
function onRemoveDependencies () {
  utils().script.clean.triggers();
  settings().clearAll();
  formService().removeForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);

  sheetService().remove.sheet(settings().sheet.template_name);
}

/**
 * --- Menu Option: "Restore Data Validation" */
function onUpdateDataValidation () { sheetService().update.validation() }

/**
 * --- Menu Option: "Restore NamedRanges" */
function onUpdateNamedRange () { sheetService().update.namedRanges() }

/**
 * --- Menu Option: "Restore Conditional Formatting" */
function onUpdateCondFormatting () { sheetService().update.conditionalFormatting() }

/**
 * ---
 * Add-on Menu option to manually run the schedule update.
 */
function onRunSchedule () {
  scheduleService().update();
}

/**
 * ---
 * Add-on Menu option to manually send emails for the next gameday
 */
function onRunEmail () {
  var ss = Config.spreadsheet();
  var isEmpty = ss.getRangeByName("squadEmail").isBlank();
  if (!isEmpty && ui().confirm.sendemail() == true) { emailService().sendMail() }
}

/**
 * ---
 * Prompts the user to enter the link for the online schedule,
 * sets it in the sheet, and sets the team name in the spreadsheet and
 * within the sheet's attached Form from the resulting schedule.
 *
 */
function onWeblinkUpdate () {
  var name_prompt = ui().confirm.teamname;
  var isConfirmed = ui().confirm.clearall;

  // Prompt to clear schedule range if it is not blank
  if (!scheduleService().isScheduleBlank()) {
    if (!isConfirmed()) { return }

    sheetService().clear.scheduleRanges();
    // Reset data validation and protections
    sheetService().update.protection();
    sheetService().update.validation();
  }

  // Prompt and set the web link
  scheduleService().setWebLink(ui().prompt.weblink());
  teamService().updateName(name_prompt);

  SpreadsheetApp.flush();
  Utilities.sleep(500);

  // Update the form title to match the team name
  formService().updateTitle(team().name);

  // Update displayed schedule
  onRunSchedule();
}

/**
 * ---
 * Detaches the active form from the spreadsheet before
 * creating a new form and attaching it.
 */
function onResetForm () {
  // Detach the attached form and clear the response sheet
  formService().removeForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);
  // Create Team Form
  onCreateForm();
}

/**
 * ---
 * Creating a new form and attaches it to the spreadsheet
 */
 function onCreateForm () {
  // Create Team Form
  formService().createForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);
  // Update the form confirmation message
  formService().updateConfirmation();
}<commit_msg>Add daily trigger Form check<commit_after>/** ****************************************************************************
*   @license                                                                   *
*   Copyright 2017 random-parts. All Rights Reserved.                          *
*                                                                              *
*   Licensed under the Apache License, Version 2.0 (the "License");            *
*   you may not use this file except in compliance with the License.           *
*   You may obtain a copy of the License at                                    *
*                                                                              *
*       http://www.apache.org/licenses/LICENSE-2.0                             *
*                                                                              *
*   Unless required by applicable law or agreed to in writing, software        *
*   distributed under the License is distributed on an "AS IS" BASIS,          *
*   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   *
*   See the License for the specific language governing permissions and        *
*   limitations under the License.                                             *
***************************************************************************** */

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*       _____               ___               _      ___  _____   _____        *
*      |_   _|__ __ _ _ __ / __|_ __  ___ _ _| |_ __| _ \/ __\ \ / / _ \       *
*        | |/ -_) _` | '  \\__ \ '_ \/ _ \ '_|  _(_-<   /\__ \\ V /|  _/       *
*        |_|\___\__,_|_|_|_|___/ .__/\___/_|  \__/__/_|_\|___/ \_/ |_|         *
*                              |_|                                             *
*                                                                              *
*        Team Sports RSVP - Team schedule management spreadsheet add-on        *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

/**
 * @file Contains the controller methods used to orchestrate script actions
 * @license Apache License, Version 2.0
 * @version 1.1.9
 */

/**
 * ---
 * Script Configuration Object for debugging. Sets the proper Spreadsheeet Object
 * depending on if the script is run as an add-on[!debug]
 * or from the script-editor[debug]
 *
 * @namespace Config
 * @property {Boolean} debug
 * @property {String} debug_ss_id - spreadsheet id for testing
 * @property {Spreadsheet} spreadsheet - `debug:` SpreadsheetByID()

 * `!debug:` ActiveSpreadsheet()
 * @property {Form} team_form - `debug:` openByUrl()
 `!debug:` getActiveForm()
 */
var Config = {
  debug: false,
  debug_ss_id: "SHEET_ID",
  spreadsheet: function () {
    if (this.debug) { return SpreadsheetApp.openById(this.debug_ss_id) }
     else { return SpreadsheetApp.getActiveSpreadsheet() }
  },
  team_form: function () {
      var form_url = this.spreadsheet().getFormUrl();
      return (form_url != null) ? FormApp.openByUrl(form_url) : null;
  }
}

/**
 * ---
 * onInstall() event that runs once. Runs the first time the add-on is installed.
 * It sets-up the triggers then runs onOpen to build the menu.
 *
 * @param {EventObject} e
 */
function onInstall (e) {
  // Install the script project triggers
  onUpdateTriggers();

  // Run to get the Add-on Menu
  onOpen(e);
}

/**
 * ---
 * onOpen() event runs the start-up processes, i.e add-on menu build,
 * when the speadsheet is opened.
 *
 * @param {EventObject} e
 */
function onOpen (e) {
  var ss = Config.spreadsheet();
  // Build the Add-On Menu
  ui().menu(e);
  SpreadsheetApp.flush();

  ss.setActiveSheet(ss.getSheets()[0]);
}

/**
 * ---
 * Auto runs the daily tasks. Set to update the schedule and then
 * process any emails that should go out for the day.
 */
function onDailyTrigger () {
  // Create a team form if one is not attached
  if (ss.getFormUrl() == null) { onCreateForm() }

  // Update the form confirmation message
  formService().updateConfirmation();

  // Update the displayed schedule
  scheduleService().update();

  // Check if emails should be sent; if so check that there is a form to send; send
  if (emailService().isEmailDay()) {
    var ss = Config.spreadsheet();
     if (ss.getFormUrl() == null) { onCreateForm() }

    emailService().sendMail();
  }
}

/**
 * ---
 * Form submit event triggers the app to update the displayed season schedule
 *
 * @param {EventObject} e
 */
function onFormSubmit (e) {
  formService().handleResponse(e);
}

/**
 * ---
 * Sheet edit event within the web schedule range triggers an update to
 * the displayed schedule when it pull changes in the schedule from the website
 *
 * @requires Installed onEdit() Trigger
 * @param {EventObject} e
 */
function onSheetEdit (e) {
  var ss = e.source;
  var range = e.range;
  var change_cell_row = e.range.rowStart;
  var change_cell_col = e.range.columnStart;
  var data_range = ss.getRangeByName("webSchedule");

  // Check if the edits are with the web data/schedule values
  if ((data_range.getRow() <= change_cell_row == change_cell_row <= data_range.getLastRow()) &&
      (data_range.getColumn() <= change_cell_col == change_cell_col <= data_range.getLastColumn())) {
    // Run the schedule update
    scheduleService().update();
  }
}

/**
 * ---
 * Creates the sheet(s) needed to run a new season. Can be run from the
 * Add-on Menu.
 *
 */
function onNewSeason () {
  var ss = Config.spreadsheet();
  var sheet_name = ui().prompt.sheetname;
  var ss_triggers = ScriptApp.getUserTriggers(ss);
  var active_sheet;
   // Install add-on triggers for this spreadsheet
   if (ss_triggers.length == 0) { onUpdateTriggers() }
   // Create a template sheet if one does not exist
   if (template(ss).getTemplate() == null) { sheetService().create.template() }

  // Create a season sheet
  sheetService().create.season(sheet_name);
  // Give it time to do what it needs to do
  Utilities.sleep(250);

  // Set the new sheet as the ActiveSheet
  active_sheet = ss.getSheets()[0];
  active_sheet.showSheet();
  ss.setActiveSheet(active_sheet);

  SpreadsheetApp.flush();
  Utilities.sleep(250);

  // Copy the returning squad mates to the new season sheet
  teamService().squad.setReturning();

  SpreadsheetApp.flush();
  Utilities.sleep(250);

  // Set the new web/online schedule link & team name
  onWeblinkUpdate();

  // Create a team form if one is not attached
  if (ss.getFormUrl() == null) { onCreateForm() }

  // Set the sheet edit protection & data validation
  sheetService().update.protection();
  sheetService().update.validation();

  // Let the user know the set-up is finished
  ui().alert.done();
}

/*******************************************************************************
*                       Menu Options - Advanced Features                       *
*******************************************************************************/

/**
 * --- Menu Option: "Extra Options Help" */
function onOptionsHelp () { ui().modal.optionsHelp() }

/**
 * --- Menu Option: "Re-install Triggers" */
function onUpdateTriggers () { utils().script.install.triggers() }

/**
 * --- Menu Option: "Remove Triggers" */
function onRemoveTriggers () { utils().script.clean.triggers() }

/**
 * --- Menu Option: "Remove Conditional Formatting" */
function onRemoveCondFormatting () { sheetService().clear.conditionalFormatting() }

/**
 * --- Menu Option: "Remove Dependencies [soft un-install]" */
function onRemoveDependencies () {
  utils().script.clean.triggers();
  settings().clearAll();
  formService().removeForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);

  sheetService().remove.sheet(settings().sheet.template_name);
}

/**
 * --- Menu Option: "Restore Data Validation" */
function onUpdateDataValidation () { sheetService().update.validation() }

/**
 * --- Menu Option: "Restore NamedRanges" */
function onUpdateNamedRange () { sheetService().update.namedRanges() }

/**
 * --- Menu Option: "Restore Conditional Formatting" */
function onUpdateCondFormatting () { sheetService().update.conditionalFormatting() }

/**
 * ---
 * Add-on Menu option to manually run the schedule update.
 */
function onRunSchedule () {
  scheduleService().update();
}

/**
 * ---
 * Add-on Menu option to manually send emails for the next gameday
 */
function onRunEmail () {
  var ss = Config.spreadsheet();
  var isEmpty = ss.getRangeByName("squadEmail").isBlank();
  if (!isEmpty && ui().confirm.sendemail() == true) { emailService().sendMail() }
}

/**
 * ---
 * Prompts the user to enter the link for the online schedule,
 * sets it in the sheet, and sets the team name in the spreadsheet and
 * within the sheet's attached Form from the resulting schedule.
 *
 */
function onWeblinkUpdate () {
  var name_prompt = ui().confirm.teamname;
  var isConfirmed = ui().confirm.clearall;

  // Prompt to clear schedule range if it is not blank
  if (!scheduleService().isScheduleBlank()) {
    if (!isConfirmed()) { return }

    sheetService().clear.scheduleRanges();
    // Reset data validation and protections
    sheetService().update.protection();
    sheetService().update.validation();
  }

  // Prompt and set the web link
  scheduleService().setWebLink(ui().prompt.weblink());
  teamService().updateName(name_prompt);

  SpreadsheetApp.flush();
  Utilities.sleep(500);

  // Update the form title to match the team name
  formService().updateTitle(team().name);

  // Update displayed schedule
  onRunSchedule();
}

/**
 * ---
 * Detaches the active form from the spreadsheet before
 * creating a new form and attaching it.
 */
function onResetForm () {
  // Detach the attached form and clear the response sheet
  formService().removeForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);
  // Create Team Form
  onCreateForm();
}

/**
 * ---
 * Creating a new form and attaches it to the spreadsheet
 */
 function onCreateForm () {
  // Create Team Form
  formService().createForm();

  SpreadsheetApp.flush();
  Utilities.sleep(500);
  // Update the form confirmation message
  formService().updateConfirmation();
}<|endoftext|>


<commit_before>/* global Blob,URL,requestAnimationFrame */
import React from 'react';
import Color from 'color';
import hterm from '../hterm';
import Component from '../component';
import { getColorList } from '../utils/colors';

export default class Term extends Component {

  constructor (props) {
    super(props);
    this.onWheel = this.onWheel.bind(this);
    this.onScrollEnter = this.onScrollEnter.bind(this);
    this.onScrollLeave = this.onScrollLeave.bind(this);
    props.ref_(this);
  }

  componentDidMount () {
    const { props } = this;
    this.term = new hterm.Terminal();

    // the first term that's created has unknown size
    // subsequent new tabs have size
    if (props.cols && props.rows) {
      this.term.realizeSize_(props.cols, props.rows);
    }

    this.term.prefs_.set('font-family', props.fontFamily);
    this.term.prefs_.set('font-size', props.fontSize);
    this.term.prefs_.set('font-smoothing', props.fontSmoothing);
    this.term.prefs_.set('cursor-color', Color(props.cursorColor).rgbString());
    this.term.prefs_.set('enable-clipboard-notice', false);
    this.term.prefs_.set('foreground-color', props.foregroundColor);
    this.term.prefs_.set('background-color', props.backgroundColor);
    this.term.prefs_.set('color-palette-overrides', getColorList(props.colors));
    this.term.prefs_.set('user-css', this.getStylesheet(props.customCSS));
    this.term.prefs_.set('scrollbar-visible', false);
    this.term.prefs_.set('receive-encoding', 'raw');
    this.term.prefs_.set('send-encoding', 'raw');
    this.term.prefs_.set('alt-sends-what', 'browser-key');

    this.term.onTerminalReady = () => {
      const io = this.term.io.push();
      io.onVTKeystroke = io.sendString = props.onData;
      io.onTerminalResize = (cols, rows) => {
        if (cols !== this.props.cols || rows !== this.props.rows) {
          props.onResize(cols, rows);
        }
      };

      // this.term.CursorNode_ is available at this point.
      this.term.setCursorShape(props.cursorShape);
    };
    this.term.decorate(this.refs.term);
    this.term.installKeyboard();
    if (this.props.onTerminal) this.props.onTerminal(this.term);

    const iframeWindow = this.getTermDocument().defaultView;
    iframeWindow.addEventListener('wheel', this.onWheel);
  }

  onWheel () {
    this.term.prefs_.set('scrollbar-visible', true);
    clearTimeout(this.scrollbarsHideTimer);
    if (!this.scrollMouseEnter) {
      this.scrollbarsHideTimer = setTimeout(() => {
        this.term.prefs_.set('scrollbar-visible', false);
      }, 1000);
    }
  }

  onScrollEnter () {
    clearTimeout(this.scrollbarsHideTimer);
    this.term.prefs_.set('scrollbar-visible', true);
    this.scrollMouseEnter = true;
  }

  onScrollLeave () {
    this.term.prefs_.set('scrollbar-visible', false);
    this.scrollMouseEnter = false;
  }

  write (data) {
    requestAnimationFrame(() => {
      this.term.io.writeUTF8(data);
    });
  }

  focus () {
    this.term.focus();
  }

  clear () {
    this.term.clearPreserveCursorRow();

    // If cursor is still not at the top, a command is probably
    // running and we'd like to delete the whole screen.
    // Move cursor to top
    if (this.term.getCursorRow() !== 0) {
      this.term.io.writeUTF8('\x1B[0;0H\x1B[2J');
    }
  }

  moveWordLeft () {
    this.term.onVTKeystroke('\x1bb');
  }

  moveWordRight () {
    this.term.onVTKeystroke('\x1bf');
  }

  deleteWordLeft () {
    this.term.onVTKeystroke('\x1b\x7f');
  }

  deleteWordRight () {
    this.term.onVTKeystroke('\x1bd');
  }

  deleteLine () {
    this.term.onVTKeystroke('\x1bw');
  }

  moveToStart () {
    this.term.onVTKeystroke('\x01');
  }

  moveToEnd () {
    this.term.onVTKeystroke('\x05');
  }

  getTermDocument () {
    return this.term.document_;
  }

  getStylesheet (css) {
    const blob = new Blob([`
      .cursor-node[focus="false"] {
        border-width: 1px !important;
      }
      ${css}
    `]);
    return URL.createObjectURL(blob, { type: 'text/css' });
  }

  componentWillReceiveProps (nextProps) {
    if (this.props.url !== nextProps.url) {
      // when the url prop changes, we make sure
      // the terminal starts or stops ignoring
      // key input so that it doesn't conflict
      // with the <webview>
      if (nextProps.url) {
        const io = this.term.io.push();
        io.onVTKeystroke = io.sendString = (str) => {
          if (1 === str.length && 3 === str.charCodeAt(0) /* Ctrl + C */) {
            this.props.onURLAbort();
          }
        };
      } else {
        this.term.io.pop();
      }
    }

    if (!this.props.cleared && nextProps.cleared) {
      this.clear();
    }

    if (this.props.fontSize !== nextProps.fontSize) {
      this.term.prefs_.set('font-size', nextProps.fontSize);
    }

    if (this.props.foregroundColor !== nextProps.foregroundColor) {
      this.term.prefs_.set('foreground-color', nextProps.foregroundColor);
    }

    if (this.props.backgroundColor !== nextProps.backgroundColor) {
      this.term.prefs_.set('background-color', nextProps.backgroundColor);
    }

    if (this.props.fontFamily !== nextProps.fontFamily) {
      this.term.prefs_.set('font-family', nextProps.fontFamily);
    }

    if (this.props.fontSmoothing !== nextProps.fontSmoothing) {
      this.term.prefs_.set('font-smoothing', nextProps.fontSmoothing);
    }

    if (this.props.cursorColor !== nextProps.cursorColor) {
      this.term.prefs_.set('cursor-color', Color(nextProps.cursorColor).rgbString());
    }

    if (this.props.cursorShape !== nextProps.cursorShape) {
      this.term.setCursorShape(nextProps.cursorShape);
    }

    if (this.props.colors !== nextProps.colors) {
      this.term.prefs_.set('color-palette-overrides', getColorList(nextProps.colors));
    }

    if (this.props.customCSS !== nextProps.customCSS) {
      this.term.prefs_.set('user-css', this.getStylesheet(nextProps.customCSS));
    }
  }

  componentWillUnmount () {
    clearTimeout(this.scrollbarsHideTimer);
    this.props.ref_(null);
  }

  template (css) {
    return

      { this.props.customChildrenBefore }

      { this.props.url
        ? <webview
            src={this.props.url}
            style={{
              background: '#000',
              position: 'absolute',
              top: 0,
              left: 0,
              display: 'inline-flex',
              width: '100%',
              height: '100%'
            }}></webview>
        :

      }
      { this.props.customChildren }

;
  }

  styles () {
    return {
      fit: {
        width: '100%',
        height: '100%'
      },

      term: {
        position: 'relative'
      },

      scrollbarShim: {
        position: 'fixed',
        right: 0,
        width: '50px',
        top: 0,
        bottom: 0
      }
    };
  }

}
<commit_msg>term: make sure shim doesn't capture clicks<commit_after>/* global Blob,URL,requestAnimationFrame */
import React from 'react';
import Color from 'color';
import hterm from '../hterm';
import Component from '../component';
import { getColorList } from '../utils/colors';

export default class Term extends Component {

  constructor (props) {
    super(props);
    this.onWheel = this.onWheel.bind(this);
    this.onScrollEnter = this.onScrollEnter.bind(this);
    this.onScrollLeave = this.onScrollLeave.bind(this);
    props.ref_(this);
  }

  componentDidMount () {
    const { props } = this;
    this.term = new hterm.Terminal();

    // the first term that's created has unknown size
    // subsequent new tabs have size
    if (props.cols && props.rows) {
      this.term.realizeSize_(props.cols, props.rows);
    }

    this.term.prefs_.set('font-family', props.fontFamily);
    this.term.prefs_.set('font-size', props.fontSize);
    this.term.prefs_.set('font-smoothing', props.fontSmoothing);
    this.term.prefs_.set('cursor-color', Color(props.cursorColor).rgbString());
    this.term.prefs_.set('enable-clipboard-notice', false);
    this.term.prefs_.set('foreground-color', props.foregroundColor);
    this.term.prefs_.set('background-color', props.backgroundColor);
    this.term.prefs_.set('color-palette-overrides', getColorList(props.colors));
    this.term.prefs_.set('user-css', this.getStylesheet(props.customCSS));
    this.term.prefs_.set('scrollbar-visible', false);
    this.term.prefs_.set('receive-encoding', 'raw');
    this.term.prefs_.set('send-encoding', 'raw');
    this.term.prefs_.set('alt-sends-what', 'browser-key');

    this.term.onTerminalReady = () => {
      const io = this.term.io.push();
      io.onVTKeystroke = io.sendString = props.onData;
      io.onTerminalResize = (cols, rows) => {
        if (cols !== this.props.cols || rows !== this.props.rows) {
          props.onResize(cols, rows);
        }
      };

      // this.term.CursorNode_ is available at this point.
      this.term.setCursorShape(props.cursorShape);
    };
    this.term.decorate(this.refs.term);
    this.term.installKeyboard();
    if (this.props.onTerminal) this.props.onTerminal(this.term);

    const iframeWindow = this.getTermDocument().defaultView;
    iframeWindow.addEventListener('wheel', this.onWheel);
  }

  onWheel () {
    this.term.prefs_.set('scrollbar-visible', true);
    clearTimeout(this.scrollbarsHideTimer);
    if (!this.scrollMouseEnter) {
      this.scrollbarsHideTimer = setTimeout(() => {
        this.term.prefs_.set('scrollbar-visible', false);
      }, 1000);
    }
  }

  onScrollEnter () {
    clearTimeout(this.scrollbarsHideTimer);
    this.term.prefs_.set('scrollbar-visible', true);
    this.scrollMouseEnter = true;
  }

  onScrollLeave () {
    this.term.prefs_.set('scrollbar-visible', false);
    this.scrollMouseEnter = false;
  }

  write (data) {
    requestAnimationFrame(() => {
      this.term.io.writeUTF8(data);
    });
  }

  focus () {
    this.term.focus();
  }

  clear () {
    this.term.clearPreserveCursorRow();

    // If cursor is still not at the top, a command is probably
    // running and we'd like to delete the whole screen.
    // Move cursor to top
    if (this.term.getCursorRow() !== 0) {
      this.term.io.writeUTF8('\x1B[0;0H\x1B[2J');
    }
  }

  moveWordLeft () {
    this.term.onVTKeystroke('\x1bb');
  }

  moveWordRight () {
    this.term.onVTKeystroke('\x1bf');
  }

  deleteWordLeft () {
    this.term.onVTKeystroke('\x1b\x7f');
  }

  deleteWordRight () {
    this.term.onVTKeystroke('\x1bd');
  }

  deleteLine () {
    this.term.onVTKeystroke('\x1bw');
  }

  moveToStart () {
    this.term.onVTKeystroke('\x01');
  }

  moveToEnd () {
    this.term.onVTKeystroke('\x05');
  }

  getTermDocument () {
    return this.term.document_;
  }

  getStylesheet (css) {
    const blob = new Blob([`
      .cursor-node[focus="false"] {
        border-width: 1px !important;
      }
      ${css}
    `]);
    return URL.createObjectURL(blob, { type: 'text/css' });
  }

  componentWillReceiveProps (nextProps) {
    if (this.props.url !== nextProps.url) {
      // when the url prop changes, we make sure
      // the terminal starts or stops ignoring
      // key input so that it doesn't conflict
      // with the <webview>
      if (nextProps.url) {
        const io = this.term.io.push();
        io.onVTKeystroke = io.sendString = (str) => {
          if (1 === str.length && 3 === str.charCodeAt(0) /* Ctrl + C */) {
            this.props.onURLAbort();
          }
        };
      } else {
        this.term.io.pop();
      }
    }

    if (!this.props.cleared && nextProps.cleared) {
      this.clear();
    }

    if (this.props.fontSize !== nextProps.fontSize) {
      this.term.prefs_.set('font-size', nextProps.fontSize);
    }

    if (this.props.foregroundColor !== nextProps.foregroundColor) {
      this.term.prefs_.set('foreground-color', nextProps.foregroundColor);
    }

    if (this.props.backgroundColor !== nextProps.backgroundColor) {
      this.term.prefs_.set('background-color', nextProps.backgroundColor);
    }

    if (this.props.fontFamily !== nextProps.fontFamily) {
      this.term.prefs_.set('font-family', nextProps.fontFamily);
    }

    if (this.props.fontSmoothing !== nextProps.fontSmoothing) {
      this.term.prefs_.set('font-smoothing', nextProps.fontSmoothing);
    }

    if (this.props.cursorColor !== nextProps.cursorColor) {
      this.term.prefs_.set('cursor-color', Color(nextProps.cursorColor).rgbString());
    }

    if (this.props.cursorShape !== nextProps.cursorShape) {
      this.term.setCursorShape(nextProps.cursorShape);
    }

    if (this.props.colors !== nextProps.colors) {
      this.term.prefs_.set('color-palette-overrides', getColorList(nextProps.colors));
    }

    if (this.props.customCSS !== nextProps.customCSS) {
      this.term.prefs_.set('user-css', this.getStylesheet(nextProps.customCSS));
    }
  }

  componentWillUnmount () {
    clearTimeout(this.scrollbarsHideTimer);
    this.props.ref_(null);
  }

  template (css) {
    return

      { this.props.customChildrenBefore }

      { this.props.url
        ? <webview
            src={this.props.url}
            style={{
              background: '#000',
              position: 'absolute',
              top: 0,
              left: 0,
              display: 'inline-flex',
              width: '100%',
              height: '100%'
            }}></webview>
        :

      }
      { this.props.customChildren }

;
  }

  styles () {
    return {
      fit: {
        width: '100%',
        height: '100%'
      },

      term: {
        position: 'relative'
      },

      scrollbarShim: {
        position: 'fixed',
        right: 0,
        width: '50px',
        top: 0,
        bottom: 0,
        pointerEvents: 'none'
      }
    };
  }

}
<|endoftext|>