<commit_before>/*
 * HOMER 5 UI (Xenophon)
 *
 * Copyright (C) 2011-2015 Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
 * Copyright (C) 2011-2015 Lorenzo Mangani <lorenzo.mangani@gmail.com> QXIP B.V.
 * License AGPL-3.0 http://opensource.org/licenses/AGPL-3.0
 *
*/

(function (angular, homer) {
    'use strict';

    angular.module(homer.modules.pages.name)
	.controller(homer.modules.pages.controllers.result, [
	    '$scope',
	    '$rootScope',
	    'eventbus',
	    '$http',
	    '$location',
	    homer.modules.core.services.search,
	    '$timeout',
	    '$window',
	    '$homerModal',
	    homer.modules.core.services.profile,
	    function ($scope,$rootScope, eventbus, $http, $location, search, $timeout, $window, $homerModal, userProfile) {

		//$rootScope.loggedIn = false;
		$scope.expandme = true;
		$scope.showtable = true;
		$scope.dataLoading = false;

		if ($rootScope.loggedIn == false) {
		    console.log("AUTH FALSE");
		    $location.path(homer.modules.auth.routes.login);
		    return;
		} else {
		    console.log("AUTH TRUE");
		}

		/* hide left menu */
		eventbus.broadcast(homer.modules.pages.events.hideLeftMenu, "1");

		$scope.$on("$destroy", function(){
		    eventbus.broadcast(homer.modules.pages.events.destroyRefresh, "1");
		    myListener();
                });

                //eventbus.broadcast(homer.modules.pages.events.resultSearchSubmit, "fullsearch");
		var myListener = eventbus.subscribe(homer.modules.pages.events.resultSearchSubmit , function(event,name, model) {
			$scope.processSearchResult();
		});

		// process the form
		$scope.processSearchResult = function() {

		/* save data for next search */
		var data = {param:{}, timestamp:{}};

		var transaction = userProfile.getProfile("transaction");
		var limit = userProfile.getProfile("limit");
		var timedate = userProfile.getProfile("timerange");
		var value = userProfile.getProfile("search");
		var node = userProfile.getProfile("node").dbnode;

		/* make construct of query */
		data.param.transaction = {};
		data.param.limit = limit;
		data.param.search = value;
		data.param.location = {};
		data.param.location.node = node;
		data.timestamp.from = timedate.from.getTime();
		data.timestamp.to = timedate.to.getTime();

		angular.forEach(transaction.transaction, function(v, k) {
		    data.param.transaction[v.name] = true;
		});
		$scope.dataLoading = true;

		search.searchByMethod(data).then(
		function (sdata) {
		    if (sdata) {
			$scope.count = sdata.length;
			$scope.gridOpts.data = sdata;
			$timeout(function () {
			    angular.element($window).resize();
			}, 0)
		    }
		},
		function(sdata) {
		    return;
		}).finally(
		function() {
		    $scope.dataLoading = false;
		    //$scope.$apply();
		});
	    };

            //$timeout(function(){
                //any code in here will automatically have an apply run afterwards
           //     $scope.$apply();
            //});

            $scope.processSearchResult();

             /* DATA */
            $scope.swapData = function() {
		//$scope.gridOpts.data = data1;
		//$scope.$apply();
	    };

	    $scope.hashCode = function(str) { // java String#hashCode
		var hash = 0;
		for (var i = 0; i < str.length; i++) {
			hash = str.charCodeAt(i) + ((hash << 5) - hash);
		}
		return hash;
	    };

	    $scope.intToARGB = function (i){
		//return ((i>>24)&0xFF).toString(16) + ((i>>16)&0xFF).toString(16) + ((i>>8)&0xFF).toString(16) + (i&0xFF).toString(16);
		return ((i>>24)&0xFF);
	    }

	    $scope.getBkgColorTable = function (callid) {
			var his = $scope.hashCode(callid);
			//var color = "#"+$scope.intToARGB(his);
			var color = "hsl("+$scope.intToARGB(his)+", 75%, 75%)";
			return {
				"background-color": color
			}
            };

	    $scope.showMessage = function(localrow, event) {
		var search_data =  {
		    timestamp: {
			from: parseInt(localrow.entity.micro_ts/1000),
			to: parseInt(localrow.entity.micro_ts/1000)
		    },
		    param: {
			search: {
			    id: parseInt(localrow.entity.id),
			    callid: localrow.entity.callid
			},
			location: {
			    node: localrow.entity.dbnode
			},
			transaction: {
			    call: false,
			    registration: false,
			    rest: false
			}
		    }
		};

		search_data['param']['transaction'][localrow.entity.trans] = true;
		var messagewindowId = ""+localrow.entity.id+"_"+localrow.entity.trans;

		$homerModal.open({
		    url: 'templates/dialogs/message.html',
		    cls: 'homer-modal-content',
		    id: "message"+messagewindowId.hashCode(),
		    divLeft: event.clientX.toString()+'px',
		    divTop: event.clientY.toString()+'px',
		    params: search_data,
		    onOpen: function() {
			console.log('modal1 message opened from url '+this.id);
		    },
		    controller: 'messageCtrl'
		});
            };

	    $scope.getColumnValue = function(row,col) {
		return row.entity[col.field+'_alias']==undefined?row.entity[col.field+'_ip']:row.entity[col.field+'_alias'];
	    }
	    $scope.getColumnTooltip = function(row,col) {
		return row.entity[col.field+'_ip'];
	    }

	    $scope.showTransaction = function(localrow,event) {

		var rows = $scope.gridApi.selection.getSelectedRows();
		var callids = [];
		var nodes = [];

		callids.push(localrow.entity.callid);

		if(callids.indexOf(localrow.entity.callid_aleg) == -1 && localrow.entity.callid_aleg.length > 1) callids.push(localrow.entity.callid_aleg);

		angular.forEach(rows, function(row, key) {
		    if(callids.indexOf(row.callid) == -1) callids.push(row.callid);
		    if(callids.indexOf(row.callid_aleg) == -1 && row.callid_aleg.length > 1) callids.push(row.callid_aleg);
		    if(nodes.indexOf(row.dbnode) == -1) nodes.push(row.dbnode);
		});

		var search_data =  {
		    timestamp: {
			from: parseInt(localrow.entity.micro_ts/1000)-300,
			to: parseInt(localrow.entity.micro_ts/1000)+300
		    },
		    param: {
			search: {
			    id: parseInt(localrow.entity.id),
			    callid: callids
			},
			location: {
			    node: nodes
			},
			transaction: {
			    call: false,
			    registration: false,
			    rest: false
			}
		    }
		};

		/* set to to our last search time */
		//var timedate = search.getTimeRange();
		var timedate = userProfile.getProfile("timerange");
		search_data['timestamp']['to'] = timedate.to.getTime();

		search_data['param']['transaction'][localrow.entity.trans] = true;
		var trwindowId = ""+localrow.entity.callid + "_" +localrow.entity.dbnode;

		nodes = userProfile.getProfile("node");
                search_data['param']['location']['node'] = nodes['dbnode'];

		$homerModal.open({
		    url: 'templates/dialogs/transaction.html',
		    cls: 'homer-modal-content',
		    id: "trans"+trwindowId.hashCode(),
		    params: search_data,
		    divLeft: event.clientX.toString()+'px',
		    divTop: event.clientY.toString()+'px',
		    onOpen: function() {
			console.log('modal1 opened from url',this.id);
		    },
		    controller: 'transactionCtrl'
		});
	    };

	    $scope.fileOneUploaded = true;
	    $scope.fileTwoUploaded = false;

	    var rowtpl =  '
'
			+ '

'
			+'
';

	    $scope.gridOpts = {
		enableColumnResizing: true,
		enableSorting: true,
		enableRowSelection: true,
		enableGridMenu: true,
		showGridFooter:true,
		noUnselect: false,
		multiSelect:true,
		modifierKeysToMultiSelect: false,
		enablePaging  : true,
		paginationPageSizes: [25, 50, 75, 100, 150, 200, 300, 400, 500, 600, 800, 1000, 2000],
		paginationPageSize: 25,
		enableFiltering: true,
		rowTemplate: rowtpl,

		filterOptions: {
		    filterText: "",
		    useExternalFilter: false
		},
		columnDefs: [
		    {field: 'id',
			displayName: 'Id',
			width: 50},
		    {field: 'milli_ts',
			displayName: 'Date',
			cellFilter: 'date:\'yyyy-MM-dd HH:mm:ss.sss\'',
			width: 170
		    },
		    //{field: 'micro_ts', displayName: 'Micro TS', width: 80},
		    {field: 'method',
			displayName: 'Method',
			cellClass: function(grid, row, col, rowRenderIndex, colRenderIndex) {
			    if (grid.getCellValue(row,col) === 'INVITE') {
				return 'blue';
			    }
			},
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'reply_reason', displayName: 'Reason', width: 70},
		    {field: 'ruri_user', displayName: 'RURI user'},
		    {field: 'from_user', displayName: 'From User'},
                    {field: 'to_user', displayName: 'To User'},
		    {field: 'callid',
			displayName: 'CallID',
			width: 160,
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'callid_aleg',
                        displayName: 'CallID_AL',
                        width: 100,
                        cellTemplate: '
{{COL_FIELD}}
'
                    },
		    {field: 'user_agent', displayName: 'User Agent'},
		    {
		        name: 'source',
		        field: 'source_alias',
			displayName: 'Source Host',
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'source_port', displayName: 'SPort', width: 50},
		    {
		        field: 'destination_alias',
			displayName: 'Destination Host',
			cellTemplate: '
{{ COL_FIELD }}
'
		    },
		    {field: 'destination_port', displayName: 'DPort', width: 50},
		    {field: 'proto', displayName: 'Proto', width: 40},
		    {field: 'node', displayName: 'Node'},
		    {field: 'custom_field1', displayName: 'Custom F1', visible: false},
		    {field: 'custom_field2', displayName: 'Custom F2', visible: false},
		    {field: 'custom_field3', displayName: 'Custom F3', visible: false}
		]
	    };

	    $scope.gridOpts.rowIdentity = function(row) {
		return row.id;
	    };

	    $scope.gridOpts.onRegisterApi = function(gridApi) {
		//set gridApi on scope
		$scope.gridApi = gridApi;
	    };
	}
    ])
    .filter('unixts', function() {

	return function(input) {
	    if (!input){
		return '';
	    } else {
		return input;
	    }
	};
     });
}(angular, homer));
<commit_msg>Semi-Center Transaction details Popup<commit_after>/*
 * HOMER 5 UI (Xenophon)
 *
 * Copyright (C) 2011-2015 Alexandr Dubovikov <alexandr.dubovikov@gmail.com>
 * Copyright (C) 2011-2015 Lorenzo Mangani <lorenzo.mangani@gmail.com> QXIP B.V.
 * License AGPL-3.0 http://opensource.org/licenses/AGPL-3.0
 *
*/

(function (angular, homer) {
    'use strict';

    angular.module(homer.modules.pages.name)
	.controller(homer.modules.pages.controllers.result, [
	    '$scope',
	    '$rootScope',
	    'eventbus',
	    '$http',
	    '$location',
	    homer.modules.core.services.search,
	    '$timeout',
	    '$window',
	    '$homerModal',
	    homer.modules.core.services.profile,
	    function ($scope,$rootScope, eventbus, $http, $location, search, $timeout, $window, $homerModal, userProfile) {

		//$rootScope.loggedIn = false;
		$scope.expandme = true;
		$scope.showtable = true;
		$scope.dataLoading = false;

		if ($rootScope.loggedIn == false) {
		    console.log("AUTH FALSE");
		    $location.path(homer.modules.auth.routes.login);
		    return;
		} else {
		    console.log("AUTH TRUE");
		}

		/* hide left menu */
		eventbus.broadcast(homer.modules.pages.events.hideLeftMenu, "1");

		$scope.$on("$destroy", function(){
		    eventbus.broadcast(homer.modules.pages.events.destroyRefresh, "1");
		    myListener();
                });

                //eventbus.broadcast(homer.modules.pages.events.resultSearchSubmit, "fullsearch");
		var myListener = eventbus.subscribe(homer.modules.pages.events.resultSearchSubmit , function(event,name, model) {
			$scope.processSearchResult();
		});

		// process the form
		$scope.processSearchResult = function() {

		/* save data for next search */
		var data = {param:{}, timestamp:{}};

		var transaction = userProfile.getProfile("transaction");
		var limit = userProfile.getProfile("limit");
		var timedate = userProfile.getProfile("timerange");
		var value = userProfile.getProfile("search");
		var node = userProfile.getProfile("node").dbnode;

		/* make construct of query */
		data.param.transaction = {};
		data.param.limit = limit;
		data.param.search = value;
		data.param.location = {};
		data.param.location.node = node;
		data.timestamp.from = timedate.from.getTime();
		data.timestamp.to = timedate.to.getTime();

		angular.forEach(transaction.transaction, function(v, k) {
		    data.param.transaction[v.name] = true;
		});
		$scope.dataLoading = true;

		search.searchByMethod(data).then(
		function (sdata) {
		    if (sdata) {
			$scope.count = sdata.length;
			$scope.gridOpts.data = sdata;
			$timeout(function () {
			    angular.element($window).resize();
			}, 0)
		    }
		},
		function(sdata) {
		    return;
		}).finally(
		function() {
		    $scope.dataLoading = false;
		    //$scope.$apply();
		});
	    };

            //$timeout(function(){
                //any code in here will automatically have an apply run afterwards
           //     $scope.$apply();
            //});

            $scope.processSearchResult();

             /* DATA */
            $scope.swapData = function() {
		//$scope.gridOpts.data = data1;
		//$scope.$apply();
	    };

	    $scope.hashCode = function(str) { // java String#hashCode
		var hash = 0;
		for (var i = 0; i < str.length; i++) {
			hash = str.charCodeAt(i) + ((hash << 5) - hash);
		}
		return hash;
	    };

	    $scope.intToARGB = function (i){
		//return ((i>>24)&0xFF).toString(16) + ((i>>16)&0xFF).toString(16) + ((i>>8)&0xFF).toString(16) + (i&0xFF).toString(16);
		return ((i>>24)&0xFF);
	    }

	    $scope.getBkgColorTable = function (callid) {
			var his = $scope.hashCode(callid);
			//var color = "#"+$scope.intToARGB(his);
			var color = "hsl("+$scope.intToARGB(his)+", 75%, 75%)";
			return {
				"background-color": color
			}
            };

	    $scope.showMessage = function(localrow, event) {
		var search_data =  {
		    timestamp: {
			from: parseInt(localrow.entity.micro_ts/1000),
			to: parseInt(localrow.entity.micro_ts/1000)
		    },
		    param: {
			search: {
			    id: parseInt(localrow.entity.id),
			    callid: localrow.entity.callid
			},
			location: {
			    node: localrow.entity.dbnode
			},
			transaction: {
			    call: false,
			    registration: false,
			    rest: false
			}
		    }
		};

		search_data['param']['transaction'][localrow.entity.trans] = true;
		var messagewindowId = ""+localrow.entity.id+"_"+localrow.entity.trans;

		$homerModal.open({
		    url: 'templates/dialogs/message.html',
		    cls: 'homer-modal-content',
		    id: "message"+messagewindowId.hashCode(),
		    divLeft: event.clientX.toString()/2+'px',
		    divTop: event.clientY.toString()+'px',
		    params: search_data,
		    onOpen: function() {
			console.log('modal1 message opened from url '+this.id);
		    },
		    controller: 'messageCtrl'
		});
            };

	    $scope.getColumnValue = function(row,col) {
		return row.entity[col.field+'_alias']==undefined?row.entity[col.field+'_ip']:row.entity[col.field+'_alias'];
	    }
	    $scope.getColumnTooltip = function(row,col) {
		return row.entity[col.field+'_ip'];
	    }

	    $scope.showTransaction = function(localrow,event) {

		var rows = $scope.gridApi.selection.getSelectedRows();
		var callids = [];
		var nodes = [];

		callids.push(localrow.entity.callid);

		if(callids.indexOf(localrow.entity.callid_aleg) == -1 && localrow.entity.callid_aleg.length > 1) callids.push(localrow.entity.callid_aleg);

		angular.forEach(rows, function(row, key) {
		    if(callids.indexOf(row.callid) == -1) callids.push(row.callid);
		    if(callids.indexOf(row.callid_aleg) == -1 && row.callid_aleg.length > 1) callids.push(row.callid_aleg);
		    if(nodes.indexOf(row.dbnode) == -1) nodes.push(row.dbnode);
		});

		var search_data =  {
		    timestamp: {
			from: parseInt(localrow.entity.micro_ts/1000)-300,
			to: parseInt(localrow.entity.micro_ts/1000)+300
		    },
		    param: {
			search: {
			    id: parseInt(localrow.entity.id),
			    callid: callids
			},
			location: {
			    node: nodes
			},
			transaction: {
			    call: false,
			    registration: false,
			    rest: false
			}
		    }
		};

		/* set to to our last search time */
		//var timedate = search.getTimeRange();
		var timedate = userProfile.getProfile("timerange");
		search_data['timestamp']['to'] = timedate.to.getTime();

		search_data['param']['transaction'][localrow.entity.trans] = true;
		var trwindowId = ""+localrow.entity.callid + "_" +localrow.entity.dbnode;

		nodes = userProfile.getProfile("node");
                search_data['param']['location']['node'] = nodes['dbnode'];

		$homerModal.open({
		    url: 'templates/dialogs/transaction.html',
		    cls: 'homer-modal-content',
		    id: "trans"+trwindowId.hashCode(),
		    params: search_data,
		    divLeft: event.clientX.toString()+'px',
		    divTop: event.clientY.toString()+'px',
		    onOpen: function() {
			console.log('modal1 opened from url',this.id);
		    },
		    controller: 'transactionCtrl'
		});
	    };

	    $scope.fileOneUploaded = true;
	    $scope.fileTwoUploaded = false;

	    var rowtpl =  '
'
			+ '

'
			+'
';

	    $scope.gridOpts = {
		enableColumnResizing: true,
		enableSorting: true,
		enableRowSelection: true,
		enableGridMenu: true,
		showGridFooter:true,
		noUnselect: false,
		multiSelect:true,
		modifierKeysToMultiSelect: false,
		enablePaging  : true,
		paginationPageSizes: [25, 50, 75, 100, 150, 200, 300, 400, 500, 600, 800, 1000, 2000],
		paginationPageSize: 25,
		enableFiltering: true,
		rowTemplate: rowtpl,

		filterOptions: {
		    filterText: "",
		    useExternalFilter: false
		},
		columnDefs: [
		    {field: 'id',
			displayName: 'Id',
			width: 50},
		    {field: 'milli_ts',
			displayName: 'Date',
			cellFilter: 'date:\'yyyy-MM-dd HH:mm:ss.sss\'',
			width: 170
		    },
		    //{field: 'micro_ts', displayName: 'Micro TS', width: 80},
		    {field: 'method',
			displayName: 'Method',
			cellClass: function(grid, row, col, rowRenderIndex, colRenderIndex) {
			    if (grid.getCellValue(row,col) === 'INVITE') {
				return 'blue';
			    }
			},
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'reply_reason', displayName: 'Reason', width: 70},
		    {field: 'ruri_user', displayName: 'RURI user'},
		    {field: 'from_user', displayName: 'From User'},
                    {field: 'to_user', displayName: 'To User'},
		    {field: 'callid',
			displayName: 'CallID',
			width: 160,
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'callid_aleg',
                        displayName: 'CallID_AL',
                        width: 100,
                        cellTemplate: '
{{COL_FIELD}}
'
                    },
		    {field: 'user_agent', displayName: 'User Agent'},
		    {
		        name: 'source',
		        field: 'source_alias',
			displayName: 'Source Host',
			cellTemplate: '
{{COL_FIELD}}
'
		    },
		    {field: 'source_port', displayName: 'SPort', width: 50},
		    {
		        field: 'destination_alias',
			displayName: 'Destination Host',
			cellTemplate: '
{{ COL_FIELD }}
'
		    },
		    {field: 'destination_port', displayName: 'DPort', width: 50},
		    {field: 'proto', displayName: 'Proto', width: 40},
		    {field: 'node', displayName: 'Node'},
		    {field: 'custom_field1', displayName: 'Custom F1', visible: false},
		    {field: 'custom_field2', displayName: 'Custom F2', visible: false},
		    {field: 'custom_field3', displayName: 'Custom F3', visible: false}
		]
	    };

	    $scope.gridOpts.rowIdentity = function(row) {
		return row.id;
	    };

	    $scope.gridOpts.onRegisterApi = function(gridApi) {
		//set gridApi on scope
		$scope.gridApi = gridApi;
	    };
	}
    ])
    .filter('unixts', function() {

	return function(input) {
	    if (!input){
		return '';
	    } else {
		return input;
	    }
	};
     });
}(angular, homer));
<|endoftext|>


<commit_before>// This will be fixed when porting functions to modules
/* eslint-disable no-use-before-define */

// Libraries
const electron = require('electron');
const app = electron.app;
const Tray = electron.Tray;
const Menu = electron.Menu;
const BrowserWindow = electron.BrowserWindow;
const ipc = electron.ipcMain;
const dialog = electron.Dialog;
const Path = require('path');
let screen;

// Check for debug option
const debug = /--debug/.test(process.argv[2]);

// Config stuff
const Configstore = require('configstore');
const pkg = require(Path.join(__dirname, 'package.json'));
const conf = new Configstore(pkg.name);

// Icon, window and app name
const appName = 'PHP Assistant';
let appIcon;
let mainWindow;
let outputWindow;

// Translation
global.i18n = require('i18n');
const locales = {
  da: 'Danish',
  de: 'Deutsch',
  en: 'English',
  fr: 'Français',
  'pt-BR': 'Português (Brasil)',
};

// Force quit variable (quitting deppends on app mode)
let forceQuit = false;

/**
 * Starting app
 */
app.on('ready', () => {
  startupRoutine();
});

/* Prepares app to run */
function startupRoutine() {
  // Get screen (display) object
  screen = electron.screen;

  // Localize (prepares i18n)
  localize();

  // Set menu
  createMenu();

  // Creates window
  mainWindow = new BrowserWindow({
    title: appName,
    height: 700,
    width: 900,
    center: true,
    titleBarStyle: 'hidden',
    icon: Path.join(__dirname, 'gfx', 'app-icon.png'),
    skipTaskbar: conf.get('general.mode') === 'tray',
  });

  // Open DevTools and maximize in debug mode
  if (debug) {
    mainWindow.openDevTools();
    mainWindow.maximize();
  }

  /* In case of closing main window */
  mainWindow.on('close', () => {
    app.quit();
  });

  // Check if phpPath is already known
  if (conf.get('php.default')) {
    // Yes! I know where PHP is!
    startApp();
  } else {
    // Nope! Go and find it!
    runCheck();
  }
}

/* In case of all windows are closed */
app.on('window-all-closed', () => {
  app.quit();
});

function startApp() {
  // Loading main HTML
  mainWindow.loadURL('file://' + Path.join(__dirname, 'index.html'));

  // Checks app mode (regular, tray)
  const mode = conf.get('general.mode');

  if (mode === 'tray') {
    createTrayIcon();
    hideAppIcon();
  }
}

function createTrayIcon() {
  // Set tray icon
  let trayIcon = Path.join(__dirname, 'gfx');
  if (process.platform !== 'darwin') {
    trayIcon = Path.join(trayIcon, 'tray.png');
  } else {
    trayIcon = Path.join(trayIcon, 'tray-black.png');
  }

  appIcon = new Tray(trayIcon);

  appIcon.setToolTip(appName);
  appIcon.on('click', focusBehavior);
}

// Hides app from taskbar/dock
function hideAppIcon() {
  if (app.dock) app.dock.hide();
}

// Behavior when clicking tray icon
function focusBehavior() {
  if (!mainWindow.isVisible()) {
    mainWindow.show();
  } else {
    mainWindow.hide();
  }
}

// Runs JS code on window main window
function runOnApp(func) {
  mainWindow.webContents.executeJavaScript(func);
}

// First run check
function runCheck() {
  mainWindow.loadURL('file://' + Path.join(__dirname, 'check.html'));
}
/**
 * Output window management
 */
ipc.on('asynchronous-message', (evt, arg) => {
  // Signal to detach output window
  if (arg === 'detach-output') {
    const outputWindowInfo = {
      title: 'PHP Assistant: ' + i18n.__('Output'),
      height: 500,
      width: 1000,
      icon: Path.join(__dirname, 'gfx', 'app-icon.png'),
      skipTaskbar: true,
    };

    // Is there any external display?
    const externalBounds = getExternalDisplayBounds();
    if (externalBounds && conf.get('presentation.try-secondary-display') === 'true') {
      outputWindowInfo.x = externalBounds.x;
      outputWindowInfo.y = externalBounds.y;
    }

    outputWindow = new BrowserWindow(outputWindowInfo);

    outputWindow.loadURL('file://' + Path.join(__dirname, 'output.html'));

    if (externalBounds) {
      outputWindow.setFullScreen(true);
    }

    // We need to tell main window that output window was closed
    outputWindow.on('closed', () => {
      // Trying that on application exit means an error
      try {
        mainWindow.webContents.executeJavaScript('outputClosed();');
      } catch (e) {
        // None... It's just exiting application...
      }
    });

    // Debug
    if (debug) {
      outputWindow.toggleDevTools();
    }
  } else if (arg === 'attach-output') {
    // Signal to re-attach output window
    outputWindow.destroy();
  }
});

ipc.on('output-channel', (evt, arg) => {
  // Is there any output window?
  if (outputWindow) {
    // Best way to avoid problems with special characters
    global.output = arg;
    outputWindow.webContents.executeJavaScript('receiveOutput()');
  }
});

/**
 * Quitting app
 */
// Force quit behavior
ipc.on('asynchronous-message', (evt, arg) => {
  if (arg === 'force-quit') terminateApp();
});

// Forces the quit
function terminateApp() {
  forceQuit = true;
  app.quit();
}

/**
 * Localization
 */
// Get translations
function localize() {
  if (!conf.get('general.locale')) {
    conf.set('general.locale', app.getLocale());
  }

  i18n.configure({
    locales: Object.keys(locales),
    directory: Path.join(__dirname, 'locales'),
  });

  i18n.fullLocaleList = locales;
  i18n.setLocale(conf.get('general.locale'));
}

/**
 * External display detection
 */
function getExternalDisplayBounds() {
  const displays = screen.getAllDisplays();
  let externalDisplay = false;

  displays.every((display) => {
    if (display.bounds.x !== 0 || display.bounds.y !== 0) {
      externalDisplay = display;
      return false; // We found it! No more searching;
    }
    return true; // Go on...
  });

  if (externalDisplay) {
    return {
      x: externalDisplay.bounds.x + 50,
      y: externalDisplay.bounds.y + 50,
    };
  }

  return false;
}

/**
 * Menu... A long, long menu...
 */

// Creates app menu
function createMenu() {
  const template = [
    {
      label: i18n.__('File'),
      submenu: [
        {
          label: i18n.__('Run code'),
          accelerator: 'CmdOrCtrl+Return',
          click: () => runOnApp('runCode()'),
        },
        {
          label: i18n.__('Clear'),
          accelerator: 'CmdOrCtrl+Shift+C',
          click: () => runOnApp('clear()'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Import from file'),
          accelerator: 'CmdOrCtrl+I',
          click: () => runOnApp('importFromFile()'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Toggle mode'),
          accelerator: 'CmdOrCtrl+T',
          click: () => runOnApp('toggleMode()'),
        },
      ]
    },
    {
      label: i18n.__('Edit'),
      submenu: [
        {
          label: i18n.__('Undo'),
          accelerator: 'CmdOrCtrl+Z',
          role: 'undo'
        },
        {
          label: i18n.__('Redo'),
          accelerator: 'Shift+CmdOrCtrl+Z',
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Cut'),
          accelerator: 'CmdOrCtrl+X',
          role: 'cut'
        },
        {
          label: i18n.__('Copy'),
          accelerator: 'CmdOrCtrl+C',
          role: 'copy'
        },
        {
          label: i18n.__('Paste'),
          accelerator: 'CmdOrCtrl+V',
          role: 'paste'
        },
        {
          label: i18n.__('Select All'),
          accelerator: 'CmdOrCtrl+A',
          role: 'selectall'
        },
      ]
    },
    {
      label: i18n.__('View'),
      submenu: [
        {
          label: i18n.__('Increase font size'),
          accelerator: 'CmdOrCtrl+=',
          click: () => runOnApp('increaseFontSize();'),
        },
        {
          label: i18n.__('Decrease font size'),
          accelerator: 'CmdOrCtrl+-',
          click: () => runOnApp('decreaseFontSize();'),
        },
        {
          label: i18n.__('Default font size'),
          accelerator: 'CmdOrCtrl+0',
          click: () => runOnApp('defaultFontSize();'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Toggle Full Screen'),
          accelerator: (() => {
            if (process.platform === 'darwin') {
              return 'Ctrl+Command+F';
            }

            return 'F11';
          })(),
          click: (item, focusedWindow) => {
            if (focusedWindow) {
              focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          }
        },
      ]
    },
    {
      label: i18n.__('Window'),
      role: 'window',
      submenu: [
        {
          label: i18n.__('Minimize'),
          accelerator: 'CmdOrCtrl+M',
          role: 'minimize'
        },
        {
          label: i18n.__('Hide'),
          accelerator: 'CmdOrCtrl+H',
          role: 'hide',
          click: () => mainWindow.hide()
        },
      ]
    },
    {
      label: i18n.__('Help'),
      role: 'help',
      submenu: [
        {
          label: appName + ' ' + i18n.__('on GitHub'),
          click: () => electron.shell.openExternal('https://github.com/rafajaques/php-assistant'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Submit an issue'),
          click: () => electron.shell.openExternal('https://github.com/rafajaques/php-assistant/issues'),
        },
      ]
    },
  ];

  // OSX specific menu
  if (process.platform === 'darwin') {
    template.unshift({
      label: appName,
      submenu: [
        {
          label: i18n.__('About') + ' ' + appName,
          click: () => runOnApp('$("#about").modal("toggle");'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Preferences') + '...',
          accelerator: 'Cmd+,',
          click: () => runOnApp('$("#settings").modal("show");'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Services'),
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Hide') + ' ' + appName,
          accelerator: 'Command+H',
          role: 'hide'
        },
        {
          label: i18n.__('Hide Others'),
          accelerator: 'Command+Alt+H',
          role: 'hideothers'
        },
        {
          label: i18n.__('Show All'),
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Quit'),
          accelerator: 'Command+Q',
          click: () => app.quit(),
        },
      ]
    });
    // Window menu.
    template[3].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('Bring All to Front'),
        role: 'front'
      }
    );
  } else {
    // If this is not OSX, set missing menus somewhere else...
    template[0].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('Preferences'),
        accelerator: 'Ctrl+P',
        click: () => runOnApp('$("#settings").modal("show");'),
      },
      {
        type: 'separator'
      },
      {
        label: i18n.__('Quit'),
        accelerator: 'Ctrl+Q',
        click: () => app.quit(),
      }
    );

    template[4].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('About') + ' ' + appName,
        click: () => runOnApp('$("#about").modal("toggle");'),
      }
    );
  }

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}
<commit_msg>Testing a welcome screen (not for building)<commit_after>// This will be fixed when porting functions to modules
/* eslint-disable no-use-before-define */

// Libraries
const electron = require('electron');
const app = electron.app;
const Tray = electron.Tray;
const Menu = electron.Menu;
const BrowserWindow = electron.BrowserWindow;
const ipc = electron.ipcMain;
const dialog = electron.Dialog;
const Path = require('path');
let screen;

// Check for debug option
const debug = /--debug/.test(process.argv[2]);

// Config stuff
const Configstore = require('configstore');
const pkg = require(Path.join(__dirname, 'package.json'));
const conf = new Configstore(pkg.name);

// Icon, window and app name
const appName = 'PHP Assistant';
let appIcon;
let mainWindow;
let outputWindow;
let welcomeWindow;

// Translation
global.i18n = require('i18n');
const locales = {
  da: 'Danish',
  de: 'Deutsch',
  en: 'English',
  fr: 'Français',
  'pt-BR': 'Português (Brasil)',
};

// Force quit variable (quitting deppends on app mode)
let forceQuit = false;

/**
 * Starting app
 */
app.on('ready', () => {
  // Update version in config file
  conf.set('version', pkg.version);

  // Wake up i18n!
  prepareLocalize();

  if (!(conf.get('general.locale'))) {
    welcome();
    return;
  }
  startupRoutine();
});

function welcome() {
  // Creates welcome window
  welcomeWindow = new BrowserWindow({
    title: appName,
    height: 580,
    width: 680,
    center: true,
    frame: false,
    resizable: false,
    icon: Path.join(__dirname, 'gfx', 'app-icon.png')
  });

  welcomeWindow.loadURL('file://' + Path.join(__dirname, 'welcome.html'));
}

/* Prepares app to run */
function startupRoutine() {
  // Get screen (display) object
  screen = electron.screen;

  // Localize (set i18n stuff)
  localize();

  // Set menu
  createMenu();

  // Creates window
  mainWindow = new BrowserWindow({
    title: appName,
    height: 700,
    width: 900,
    center: true,
    titleBarStyle: 'hidden',
    icon: Path.join(__dirname, 'gfx', 'app-icon.png'),
    skipTaskbar: conf.get('general.mode') === 'tray',
  });

  // Open DevTools and maximize in debug mode
  if (debug) {
    mainWindow.openDevTools();
    mainWindow.maximize();
  }

  /* In case of closing main window */
  mainWindow.on('close', () => {
    app.quit();
  });

  // Check if phpPath is already known
  if (conf.get('php.default')) {
    // Yes! I know where PHP is!
    startApp();
  } else {
    // Nope! Go and find it!
    runCheck();
  }
}

/* In case of all windows are closed */
app.on('window-all-closed', () => {
  app.quit();
});

function startApp() {
  // Loading main HTML
  mainWindow.loadURL('file://' + Path.join(__dirname, 'index.html'));

  // Checks app mode (regular, tray)
  const mode = conf.get('general.mode');

  if (mode === 'tray') {
    createTrayIcon();
    hideAppIcon();
  }
}

function createTrayIcon() {
  // Set tray icon
  let trayIcon = Path.join(__dirname, 'gfx');
  if (process.platform !== 'darwin') {
    trayIcon = Path.join(trayIcon, 'tray.png');
  } else {
    trayIcon = Path.join(trayIcon, 'tray-black.png');
  }

  appIcon = new Tray(trayIcon);

  appIcon.setToolTip(appName);
  appIcon.on('click', focusBehavior);
}

// Hides app from taskbar/dock
function hideAppIcon() {
  if (app.dock) app.dock.hide();
}

// Behavior when clicking tray icon
function focusBehavior() {
  if (!mainWindow.isVisible()) {
    mainWindow.show();
  } else {
    mainWindow.hide();
  }
}

// Runs JS code on window main window
function runOnApp(func) {
  mainWindow.webContents.executeJavaScript(func);
}

// First run check
function runCheck() {
  mainWindow.loadURL('file://' + Path.join(__dirname, 'check.html'));
}
/**
 * Output window management
 */
ipc.on('asynchronous-message', (evt, arg) => {
  // Signal to detach output window
  if (arg === 'detach-output') {
    const outputWindowInfo = {
      title: 'PHP Assistant: ' + i18n.__('Output'),
      height: 500,
      width: 1000,
      icon: Path.join(__dirname, 'gfx', 'app-icon.png'),
      skipTaskbar: true,
    };

    // Is there any external display?
    const externalBounds = getExternalDisplayBounds();
    if (externalBounds && conf.get('presentation.try-secondary-display') === 'true') {
      outputWindowInfo.x = externalBounds.x;
      outputWindowInfo.y = externalBounds.y;
    }

    outputWindow = new BrowserWindow(outputWindowInfo);

    outputWindow.loadURL('file://' + Path.join(__dirname, 'output.html'));

    if (externalBounds) {
      outputWindow.setFullScreen(true);
    }

    // We need to tell main window that output window was closed
    outputWindow.on('closed', () => {
      // Trying that on application exit means an error
      try {
        mainWindow.webContents.executeJavaScript('outputClosed();');
      } catch (e) {
        // None... It's just exiting application...
      }
    });

    // Debug
    if (debug) {
      outputWindow.toggleDevTools();
    }
  } else if (arg === 'attach-output') {
    // Signal to re-attach output window
    outputWindow.destroy();
  }
});

ipc.on('output-channel', (evt, arg) => {
  // Is there any output window?
  if (outputWindow) {
    // Best way to avoid problems with special characters
    global.output = arg;
    outputWindow.webContents.executeJavaScript('receiveOutput()');
  }
});

/**
 * Quitting app
 */
// Force quit behavior
ipc.on('asynchronous-message', (evt, arg) => {
  if (arg === 'force-quit') terminateApp();
});

// Forces the quit
function terminateApp() {
  forceQuit = true;
  app.quit();
}

/**
 * Localization
 */
function prepareLocalize() {
  i18n.configure({
    locales: Object.keys(locales),
    directory: Path.join(__dirname, 'locales'),
  });

  i18n.fullLocaleList = locales;
}
// Get translations
function localize() {
  if (!conf.get('general.locale')) {
    conf.set('general.locale', app.getLocale());
  }

  i18n.setLocale(conf.get('general.locale'));
}

/**
 * External display detection
 */
function getExternalDisplayBounds() {
  const displays = screen.getAllDisplays();
  let externalDisplay = false;

  displays.every((display) => {
    if (display.bounds.x !== 0 || display.bounds.y !== 0) {
      externalDisplay = display;
      return false; // We found it! No more searching;
    }
    return true; // Go on...
  });

  if (externalDisplay) {
    return {
      x: externalDisplay.bounds.x + 50,
      y: externalDisplay.bounds.y + 50,
    };
  }

  return false;
}

/**
 * Menu... A long, long menu...
 */

// Creates app menu
function createMenu() {
  const template = [
    {
      label: i18n.__('File'),
      submenu: [
        {
          label: i18n.__('Run code'),
          accelerator: 'CmdOrCtrl+Return',
          click: () => runOnApp('runCode()'),
        },
        {
          label: i18n.__('Clear'),
          accelerator: 'CmdOrCtrl+Shift+C',
          click: () => runOnApp('clear()'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Import from file'),
          accelerator: 'CmdOrCtrl+I',
          click: () => runOnApp('importFromFile()'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Toggle mode'),
          accelerator: 'CmdOrCtrl+T',
          click: () => runOnApp('toggleMode()'),
        },
      ]
    },
    {
      label: i18n.__('Edit'),
      submenu: [
        {
          label: i18n.__('Undo'),
          accelerator: 'CmdOrCtrl+Z',
          role: 'undo'
        },
        {
          label: i18n.__('Redo'),
          accelerator: 'Shift+CmdOrCtrl+Z',
          role: 'redo'
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Cut'),
          accelerator: 'CmdOrCtrl+X',
          role: 'cut'
        },
        {
          label: i18n.__('Copy'),
          accelerator: 'CmdOrCtrl+C',
          role: 'copy'
        },
        {
          label: i18n.__('Paste'),
          accelerator: 'CmdOrCtrl+V',
          role: 'paste'
        },
        {
          label: i18n.__('Select All'),
          accelerator: 'CmdOrCtrl+A',
          role: 'selectall'
        },
      ]
    },
    {
      label: i18n.__('View'),
      submenu: [
        {
          label: i18n.__('Increase font size'),
          accelerator: 'CmdOrCtrl+=',
          click: () => runOnApp('increaseFontSize();'),
        },
        {
          label: i18n.__('Decrease font size'),
          accelerator: 'CmdOrCtrl+-',
          click: () => runOnApp('decreaseFontSize();'),
        },
        {
          label: i18n.__('Default font size'),
          accelerator: 'CmdOrCtrl+0',
          click: () => runOnApp('defaultFontSize();'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Toggle Full Screen'),
          accelerator: (() => {
            if (process.platform === 'darwin') {
              return 'Ctrl+Command+F';
            }

            return 'F11';
          })(),
          click: (item, focusedWindow) => {
            if (focusedWindow) {
              focusedWindow.setFullScreen(!focusedWindow.isFullScreen());
            }
          }
        },
      ]
    },
    {
      label: i18n.__('Window'),
      role: 'window',
      submenu: [
        {
          label: i18n.__('Minimize'),
          accelerator: 'CmdOrCtrl+M',
          role: 'minimize'
        },
        {
          label: i18n.__('Hide'),
          accelerator: 'CmdOrCtrl+H',
          role: 'hide',
          click: () => mainWindow.hide()
        },
      ]
    },
    {
      label: i18n.__('Help'),
      role: 'help',
      submenu: [
        {
          label: appName + ' ' + i18n.__('on GitHub'),
          click: () => electron.shell.openExternal('https://github.com/rafajaques/php-assistant'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Submit an issue'),
          click: () => electron.shell.openExternal('https://github.com/rafajaques/php-assistant/issues'),
        },
      ]
    },
  ];

  // OSX specific menu
  if (process.platform === 'darwin') {
    template.unshift({
      label: appName,
      submenu: [
        {
          label: i18n.__('About') + ' ' + appName,
          click: () => runOnApp('$("#about").modal("toggle");'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Preferences') + '...',
          accelerator: 'Cmd+,',
          click: () => runOnApp('$("#settings").modal("show");'),
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Services'),
          role: 'services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Hide') + ' ' + appName,
          accelerator: 'Command+H',
          role: 'hide'
        },
        {
          label: i18n.__('Hide Others'),
          accelerator: 'Command+Alt+H',
          role: 'hideothers'
        },
        {
          label: i18n.__('Show All'),
          role: 'unhide'
        },
        {
          type: 'separator'
        },
        {
          label: i18n.__('Quit'),
          accelerator: 'Command+Q',
          click: () => app.quit(),
        },
      ]
    });
    // Window menu.
    template[3].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('Bring All to Front'),
        role: 'front'
      }
    );
  } else {
    // If this is not OSX, set missing menus somewhere else...
    template[0].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('Preferences'),
        accelerator: 'Ctrl+P',
        click: () => runOnApp('$("#settings").modal("show");'),
      },
      {
        type: 'separator'
      },
      {
        label: i18n.__('Quit'),
        accelerator: 'Ctrl+Q',
        click: () => app.quit(),
      }
    );

    template[4].submenu.push(
      {
        type: 'separator'
      },
      {
        label: i18n.__('About') + ' ' + appName,
        click: () => runOnApp('$("#about").modal("toggle");'),
      }
    );
  }

  const menu = Menu.buildFromTemplate(template);
  Menu.setApplicationMenu(menu);
}
<|endoftext|>


<commit_before>(function() {'use strict';

  const { app } = require('electron');

  global.Relief = {
    env: require('./lib/env'),
    log: require('./lib/log'),
    window: require('./lib/window'),
    persistence: require('./lib/persistence/persistence'),
    get blockchain() {
      return require('./lib/blockchain/blockchain')(Relief);
    },
    get user() {
      return require('./lib/user')(Relief);
    },
  };

  app.on('ready', function() {
    const mainWindow = Relief.window.createWindow();
  });

  app.on('window-all-closed', function() {
    app.quit();
  });

  Relief.log.info('Starting application...');
  Relief.log.info('Version: ', Relief.env.version);

  const onPersistenceInit = function(err) {
    if (err) {
      Relief.log.error(err);
      process.exit();
    }
    Relief.blockchain.init(onBlockchainInit);
  };

  const onBlockchainInit = function(err) {
    if (err) {
      Relief.log.error(err);
    }
  };

  Relief.persistence.init(onPersistenceInit);

}());
<commit_msg>add plugin to global obj<commit_after>(function() {'use strict';

  const { app } = require('electron');

  global.Relief = {
    env: require('./lib/env'),
    log: require('./lib/log'),
    window: require('./lib/window'),
    plugin: require('./lib/plugin'),
    persistence: require('./lib/persistence/persistence'),
    get blockchain() {
      return require('./lib/blockchain/blockchain')(Relief);
    },
    get user() {
      return require('./lib/user')(Relief);
    },
  };

  app.on('ready', function() {
    const mainWindow = Relief.window.createWindow();
  });

  app.on('window-all-closed', function() {
    app.quit();
  });

  Relief.log.info('Starting application...');
  Relief.log.info('Version: ', Relief.env.version);

  const onPersistenceInit = function(err) {
    if (err) {
      Relief.log.error(err);
      process.exit();
    }
    Relief.blockchain.init(onBlockchainInit);
  };

  const onBlockchainInit = function(err) {
    if (err) {
      Relief.log.error(err);
    }
  };

  Relief.persistence.init(onPersistenceInit);

}());
<|endoftext|>


<commit_before>const {app, BrowserWindow} = require('electron')
const fs = require('fs');
const homeOrTmp = require('home-or-tmp');

function createWindow() {

    // Create the browser window.
    let win = new BrowserWindow({
        fullscreen : true,
        kiosk      : true,
        toolbar    : false,
        frame      : false,
        alwaysOnTop: true,
        resizable  : false,
        title      : "Frosch",
        icon       : `${__dirname}/icono.png`,

        webPreferences: {
            nodeIntegration: true
        }
    })

    win.webContents.openDevTools();

    // and load the index.html of the app.
    win.loadURL(`file://${__dirname}/main.html`, {
        base: `/${__dirname}`
    });

    win.onerror = (errorMsg, url, lineNumber, colNumber) => {

        const now = new Date();
        const mensaje = now.toString() + ' ' + errorMsg + '@' + url + ':' + lineNumber + '.' + colNumber;
        fs.appendFile(homeOrTmp + '/errores.txt', mensaje);
    };

}

app.whenReady().then(createWindow)
<commit_msg>Se quita devtools<commit_after>const {app, BrowserWindow} = require('electron')
const fs = require('fs');
const homeOrTmp = require('home-or-tmp');

function createWindow() {

    // Create the browser window.
    let win = new BrowserWindow({
        fullscreen : true,
        kiosk      : true,
        toolbar    : false,
        frame      : false,
        alwaysOnTop: true,
        resizable  : false,
        title      : "Frosch",
        icon       : `${__dirname}/icono.png`,

        webPreferences: {
            nodeIntegration: true
        }
    })

    // and load the index.html of the app.
    win.loadURL(`file://${__dirname}/main.html`, {
        base: `/${__dirname}`
    });

    win.onerror = (errorMsg, url, lineNumber, colNumber) => {

        const now = new Date();
        const mensaje = now.toString() + ' ' + errorMsg + '@' + url + ':' + lineNumber + '.' + colNumber;
        fs.appendFile(homeOrTmp + '/errores.txt', mensaje);
    };

}

app.whenReady().then(createWindow)
<|endoftext|>


<commit_before>import React from "react";
import { Container } from "reactstrap";
import './styles.scss'
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'

const Remarkable = require('remarkable');

const md = new Remarkable();
md.set({
  breaks: true,
  linkify: true
});

return (
   <React.Fragment>

Welcome to the 1st Draft!

Contents

The World Needs This Because: (v1)

The World Needs This Because: (v2)

1. Abstract

1.1. Background

	1.2. Public Happiness Movement Token Introduction

2. Problem Statement

	2.1. Issues we aim to solve

	2.2. Primary Goal

	2.3. Secondary Goal

	2.4. Relation to Universal Basic Income

3. Educating the Public about Blockchain

	3.1. Current State of Public Understanding

	3.2. Reaching a New Audience

4. The Public Happiness Movement Token

	4.1. Token Overview

5. Public Happiness Movement Token ICO

	5.1. ICO Strategy

	5.2. ICO Stages

	5.3. Ongoing Funding for Specific Projects and Experts

	5.4. ICO Marketing

6. Public Happiness – Background

	6.1. Community Background

	6.2. The Public Happiness Movement Community

7. Platform Overview

	7.1. The Public Happiness Map (public actions for increasing human and society well-being)

	7.2. Action Center (Microvolunteering)

	7.3. Community News

	7.4. Active Happiness Shop

	7.5. Who Defines What is Accepted as ‘Public Happiness’

	7.6. Evidence Based and Peer Reviewed Actions

	7.7. Who can Participate on the Platform

	7.8. Pre-existing Communities with Similar Values

	7.9. Languages

	7.10. Decentralised Governance and Voting

8. The Path to Decentralisation

	8.1. Benevolent Dictatorship vs Complete Community Governance

	8.2. Example Scenario: Outside Collusion

	8.3. Lines of Defence

	8.4. Conclusion

9. Security
	9.1. Levels of Trust
	9.2.. Community Administrators
	9.3. Project Administrators
	9.4. Mining Limits
	9.5. Cold Storage and Key Holders

10. Marketing Strategy
	10.1. A New Level of Hash tagging
	10.2. Bus Tour
	10.3.. Public Happiness Channel
	10.4. Happy Cam
	10.5. Public Happiness Partners
	10.6. Online Supporters
	10.7. Contests
	10.8. Collectables

11.  Automated Token Distribution Matrix
	11.1. Weighted Mining
	11.2. Hard Cap
	11.3. Adjusting the Balancing
	11.4. Token Release
	11.5. Mining Table
	11.6. Experience Multipliers
	11.7. Token Distribution
	11.8. Further Matrix Considerations

12. Team
	12.1. Current Team Members
	12.2. Positions Open
	12.3. Remuneration
	12.4. Facilities

13. Platform Technicals
	13.1. Crypto Linking Bridges
	13.2. Trello vs Wekan vs Other Solutions
	13.3. Leaflet.js vs Google Maps API
	13.4. Switching the Platform to the Dapps Network

14. Doomsday Protocol
	14.1. Huge Market Crash
	14.2. Quantum Security
	14.3. Massive Hack
	14.4. Zombie Apocalypse

15. Giving Back to Open-source
16. Timeline
17. White Paper Reviewed By
18. Questions to be Resolved

 </React.Fragment>
 );
}

const markdownSection1 = md.render("
#Public Happiness Movement Token
#Whitepaper

**Foreword:**

I've lived about as frugal a life as is possible in the Western World because I've always disliked money.  It so often seems to have a negative effect on people and society.

The crypto-world has me intensely curious, because money can be different there. I wanted to learn more and see if it's possible to design a form of money that is intrinsically tied to creating societal value.  Something to act as a band-aid on today’s ‘profit at all costs’ capitalism which has blind-spots for large areas critical to producing healthy, happy societies. This is caused by foundations measuring all progress and success as an increase in GDP. Anything which doesn’t is, by design, an after-thought.

GDP was designed by Simon Kuznets, in 1937 as a temporary post war recovery system, but the beast got out of control. The damage caused to humanity by basing our decision making processes on measurements of GDP isn’t even contentious anymore. [Here’s a list](http://ec.europa.eu/environment/beyond_gdp/key_quotes_en.html) of global and economic leaders stating the need to move past it.

This token is an effort to create a new monetary and economic system. One which focuses energy onto these essential societal areas which are currently overlooked. An effort to create a healthier and happier world.

**Intro:**

If the right people get behind this it will have a profound effect on increasing peace, happiness, and reducing human-suffering across the world. If you’re reading this it because we believe that you have the skills to contribute, and a passion to create positive change for humanity.

"Those who love peace must learn to organize as effectively as those who love war"  - Martin Luther King

Our community of volunteers has been gradually building a platform to host this vision for over 3 years now. The platform is for groups from around the world, anyone who is using positive actions to promote peace and wellbeing through building human and community connection.

It's provides a space for our individual networks to grow into something larger. A global movement for a world with more peace and happiness in it. We’ve reached the point where it is ready to begin hosting communities who will contribute to it governance and improving the platform. You can take a look here: [focallocal.org ](https://focallocal.org)

Note: This white paper is quite long. The most effective way to contribute is by reading the intro and why ‘the world needs this’, and then clicking the sections in the contents page which you’d most like to contribute to. To discuss a section and make suggestions, click on the red balloons.")

const markdownSection2 = md.render("INSERT SECTION 2 HERE")
const markdownSection3 = md.render("INSERT SECTION 3 HERE")
const markdownSection4 = md.render("INSERT SECTION 4 HERE")

const index = (props) => {
  return (
    <Container className="mt-5">

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" dcsTags={props.dcsTags} />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal1" display="inline" dcsTags={props.dcsTags} />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal2" display="inline" dcsTags={props.dcsTags} />

    </Container>

  );
};

export default index;
<commit_msg>fixed by Arty<commit_after>import React from "react";
import { Container } from "reactstrap";
import './styles.scss'
import DCSBalloon from '/imports/client/ui/components/DCSBalloon/index.js'

const Remarkable = require('remarkable');

const md = new Remarkable();
md.set({
  breaks: true,
  linkify: true
});

const Contents = () => (
   <React.Fragment>

Welcome to the 1st Draft!

Contents

The World Needs This Because: (v1)

The World Needs This Because: (v2)

1. Abstract

1.1. Background

	1.2. Public Happiness Movement Token Introduction

2. Problem Statement

	2.1. Issues we aim to solve

	2.2. Primary Goal

	2.3. Secondary Goal

	2.4. Relation to Universal Basic Income

3. Educating the Public about Blockchain

	3.1. Current State of Public Understanding

	3.2. Reaching a New Audience

4. The Public Happiness Movement Token

	4.1. Token Overview

5. Public Happiness Movement Token ICO

	5.1. ICO Strategy

	5.2. ICO Stages

	5.3. Ongoing Funding for Specific Projects and Experts

	5.4. ICO Marketing

6. Public Happiness – Background

	6.1. Community Background

	6.2. The Public Happiness Movement Community

7. Platform Overview

	7.1. The Public Happiness Map (public actions for increasing human and society well-being)

	7.2. Action Center (Microvolunteering)

	7.3. Community News

	7.4. Active Happiness Shop

	7.5. Who Defines What is Accepted as ‘Public Happiness’

	7.6. Evidence Based and Peer Reviewed Actions

	7.7. Who can Participate on the Platform

	7.8. Pre-existing Communities with Similar Values

	7.9. Languages

	7.10. Decentralised Governance and Voting

8. The Path to Decentralisation

	8.1. Benevolent Dictatorship vs Complete Community Governance

	8.2. Example Scenario: Outside Collusion

	8.3. Lines of Defence

	8.4. Conclusion

9. Security
	9.1. Levels of Trust
	9.2.. Community Administrators
	9.3. Project Administrators
	9.4. Mining Limits
	9.5. Cold Storage and Key Holders

10. Marketing Strategy
	10.1. A New Level of Hash tagging
	10.2. Bus Tour
	10.3.. Public Happiness Channel
	10.4. Happy Cam
	10.5. Public Happiness Partners
	10.6. Online Supporters
	10.7. Contests
	10.8. Collectables

11.  Automated Token Distribution Matrix
	11.1. Weighted Mining
	11.2. Hard Cap
	11.3. Adjusting the Balancing
	11.4. Token Release
	11.5. Mining Table
	11.6. Experience Multipliers
	11.7. Token Distribution
	11.8. Further Matrix Considerations

12. Team
	12.1. Current Team Members
	12.2. Positions Open
	12.3. Remuneration
	12.4. Facilities

13. Platform Technicals
	13.1. Crypto Linking Bridges
	13.2. Trello vs Wekan vs Other Solutions
	13.3. Leaflet.js vs Google Maps API
	13.4. Switching the Platform to the Dapps Network

14. Doomsday Protocol
	14.1. Huge Market Crash
	14.2. Quantum Security
	14.3. Massive Hack
	14.4. Zombie Apocalypse

15. Giving Back to Open-source
16. Timeline
17. White Paper Reviewed By
18. Questions to be Resolved

 </React.Fragment>
 )

const markdownSection1 = md.render(`
#Public Happiness Movement Token
#Whitepaper

**Foreword:**

I've lived about as frugal a life as is possible in the Western World because I've always disliked money.  It so often seems to have a negative effect on people and society.

The crypto-world has me intensely curious, because money can be different there. I wanted to learn more and see if it's possible to design a form of money that is intrinsically tied to creating societal value.  Something to act as a band-aid on today’s ‘profit at all costs’ capitalism which has blind-spots for large areas critical to producing healthy, happy societies. This is caused by foundations measuring all progress and success as an increase in GDP. Anything which doesn’t is, by design, an after-thought.

GDP was designed by Simon Kuznets, in 1937 as a temporary post war recovery system, but the beast got out of control. The damage caused to humanity by basing our decision making processes on measurements of GDP isn’t even contentious anymore. [Here’s a list](http://ec.europa.eu/environment/beyond_gdp/key_quotes_en.html) of global and economic leaders stating the need to move past it.

This token is an effort to create a new monetary and economic system. One which focuses energy onto these essential societal areas which are currently overlooked. An effort to create a healthier and happier world.

**Intro:**

If the right people get behind this it will have a profound effect on increasing peace, happiness, and reducing human-suffering across the world. If you’re reading this it because we believe that you have the skills to contribute, and a passion to create positive change for humanity.

"Those who love peace must learn to organize as effectively as those who love war"  - Martin Luther King

Our community of volunteers has been gradually building a platform to host this vision for over 3 years now. The platform is for groups from around the world, anyone who is using positive actions to promote peace and wellbeing through building human and community connection.

It's provides a space for our individual networks to grow into something larger. A global movement for a world with more peace and happiness in it. We’ve reached the point where it is ready to begin hosting communities who will contribute to it governance and improving the platform. You can take a look here: [focallocal.org ](https://focallocal.org)

Note: This white paper is quite long. The most effective way to contribute is by reading the intro and why ‘the world needs this’, and then clicking the sections in the contents page which you’d most like to contribute to. To discuss a section and make suggestions, click on the red balloons.`)

const markdownSection2 = md.render("INSERT SECTION 2 HERE")
const markdownSection3 = md.render("INSERT SECTION 3 HERE")
const markdownSection4 = md.render("INSERT SECTION 4 HERE")

const index = (props) => {
  return (
    <Container className="mt-5">
			<Contents />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal" display="inline" dcsTags={props.dcsTags} />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal1" display="inline" dcsTags={props.dcsTags} />

      <DCSBalloon title="Insert title" subtitle="Insert subtitle" balloonId="bal2" display="inline" dcsTags={props.dcsTags} />

    </Container>

  );
};

export default index;
<|endoftext|>


<commit_before>'use strict';

const {
  app,
  Menu,
  Tray,
  BrowserWindow,
  globalShortcut,
  ipcMain,
  clipboard,
  dialog,
  shell } = require('electron');

const path = require('path');

let mainWindow    = null;
let tray          = null;
let updateOffered = false;

// Hide the icon from the dock if the OS has it.
if (app.dock) {
  app.dock.hide();
}

app.on('ready', () => {
  mainWindow = new BrowserWindow({
    frame: false,
    height: 396,
    width: 300,
    backgroundColor: '#2B2F3B',
    resizable: false,
    center: true,
    skipTaskbar: true,
    show: false,
    title: 'Brownie'
  });

  // The trigger used to show/hide the app window.
  // TODO: allow user to set a custom shortcut.
  globalShortcut.register('Alt+Space', () => {
    if (mainWindow.isVisible()) {
      if (app.hide) {
        // NOTE: to get focus back to the previous window on MacOS we need to
        // hide the app not only the window.
        app.hide();
      } else {
        // NOTE: Windows doesn't have app.hide method, but combination of
        // window.blur and window.hide does the same thing.
        mainWindow.blur();
        mainWindow.hide()
      }
    } else {
      mainWindow.show();
    }
  });

  tray = new Tray(path.join(__dirname, 'img', 'tray_icon_black_18.png'));

  const contextMenu = Menu.buildFromTemplate([
    { label: 'Clear clipboard history', click(item, focusedWindow) {
      mainWindow.webContents.send('clearClipboardHistory');
    }},
    { type: 'separator' },
    { label: 'Quit Olden', click(item, focusedWindow) {
      app.quit();
    }}
  ]);

  tray.setToolTip('Olden')
  tray.setContextMenu(contextMenu)

  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.setVisibleOnAllWorkspaces(true);
  // TODO: execute the line below based on the input argument value.
  mainWindow.webContents.openDevTools();

  ipcMain.on('hideWindow', (event) => {
    if (app.hide) {
        app.hide();
      } else {
        mainWindow.blur();
        mainWindow.hide()
      }
  });

  ipcMain.on('offer-update', (event, data) => {
    if (!updateOffered) {
      dialog.showMessageBox({
        type:      'question',
        buttons:   [ 'Cancel', 'Download' ],
        defaultId: 0,
        title:     'A newer version of Olden is available',
        message:   'Would you like to download the update?'
      }, (response) => {
        if (response === 1) {
          shell.openExternal(data.url);
        }

        updateOffered = true;
      });
    }
  });
});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On MacOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
<commit_msg>Comments out dev tool code<commit_after>'use strict';

const {
  app,
  Menu,
  Tray,
  BrowserWindow,
  globalShortcut,
  ipcMain,
  clipboard,
  dialog,
  shell } = require('electron');

const path = require('path');

let mainWindow    = null;
let tray          = null;
let updateOffered = false;

// Hide the icon from the dock if the OS has it.
if (app.dock) {
  app.dock.hide();
}

app.on('ready', () => {
  mainWindow = new BrowserWindow({
    frame: false,
    height: 396,
    width: 300,
    backgroundColor: '#2B2F3B',
    resizable: false,
    center: true,
    skipTaskbar: true,
    show: false,
    title: 'Brownie'
  });

  // The trigger used to show/hide the app window.
  // TODO: allow user to set a custom shortcut.
  globalShortcut.register('Alt+Space', () => {
    if (mainWindow.isVisible()) {
      if (app.hide) {
        // NOTE: to get focus back to the previous window on MacOS we need to
        // hide the app not only the window.
        app.hide();
      } else {
        // NOTE: Windows doesn't have app.hide method, but combination of
        // window.blur and window.hide does the same thing.
        mainWindow.blur();
        mainWindow.hide()
      }
    } else {
      mainWindow.show();
    }
  });

  tray = new Tray(path.join(__dirname, 'img', 'tray_icon_black_18.png'));

  const contextMenu = Menu.buildFromTemplate([
    { label: 'Clear clipboard history', click(item, focusedWindow) {
      mainWindow.webContents.send('clearClipboardHistory');
    }},
    { type: 'separator' },
    { label: 'Quit Olden', click(item, focusedWindow) {
      app.quit();
    }}
  ]);

  tray.setToolTip('Olden')
  tray.setContextMenu(contextMenu)

  mainWindow.loadURL('file://' + __dirname + '/index.html');
  mainWindow.setVisibleOnAllWorkspaces(true);
  // TODO: execute the line below based on the input argument value.
  // mainWindow.webContents.openDevTools();

  ipcMain.on('hideWindow', (event) => {
    if (app.hide) {
        app.hide();
      } else {
        mainWindow.blur();
        mainWindow.hide()
      }
  });

  ipcMain.on('offer-update', (event, data) => {
    if (!updateOffered) {
      dialog.showMessageBox({
        type:      'question',
        buttons:   [ 'Cancel', 'Download' ],
        defaultId: 0,
        title:     'A newer version of Olden is available',
        message:   'Would you like to download the update?'
      }, (response) => {
        if (response === 1) {
          shell.openExternal(data.url);
        }

        updateOffered = true;
      });
    }
  });
});

// Quit when all windows are closed.
app.on('window-all-closed', () => {
  // On MacOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
<|endoftext|>


<commit_before>export canConfigureName from './canConfigureName.js';
export getPropertiesList from './getPropertiesList.js';
export isObject from './isObject.js';
export muteProperty from './muteProperty.js';
export prepareArguments from './prepareArguments';
export typeReviver from './typeReviver.js';
export typeReplacer from './typeReplacer.js';
<commit_msg>Fix new lint errors<commit_after>export canConfigureName from './canConfigureName';
export getPropertiesList from './getPropertiesList';
export isObject from './isObject';
export muteProperty from './muteProperty';
export prepareArguments from './prepareArguments';
export typeReviver from './typeReviver';
export typeReplacer from './typeReplacer';
<|endoftext|>


<commit_before>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';

import { query } from '/lib/views';
import { here } from '/lib/utils';
import { Transactions } from '/imports/api/transactions/Transactions';
import { Contracts } from '/imports/api/contracts/Contracts';
import { getUser } from '/imports/ui/templates/components/identity/avatar/avatar';

import '/imports/ui/templates/widgets/tally/tally.html';

/**
* @summary translates data info about vote into a renderable contracts
* @param {object} post a transaction Object
*/
const _voteToContract = (post, contract, hidePost, winningBallot, openFeed) => {
  const transaction = {
    _id: post._id,
    ballot: post.condition.ballot,
    senderId: post.input.entityId,
    receiverId: post.output.entityId,
    isVote: true,
    hidePost,
    winningBallot,
    isRevoke: (post.input.entityType !== 'INDIVIDUAL'),
  };
  if (openFeed) {
    // for a feed in a general context (home page)
    if (post.kind === 'DELEGATION') {
      if (post.input.entityType === 'CONTRACT') {
        transaction.senderId = post.input.delegateId;
      } else if (post.output.entityType === 'CONTRACT') {
        transaction.receiverId = post.output.delegateId;
      }
      transaction.isVote = false;
    }
    transaction.contract = {
      timestamp: post.timestamp,
      kind: post.kind,
      wallet: {
        balance: post.output.quantity,
      },
      _id: post._id,
    };
  } else if (contract) {
    transaction.contract = {
      _id: contract._id,
      timestamp: post.timestamp,
      wallet: {
        balance: post.input.quantity,
      },
      title: contract.title,
      url: contract.url,
    };
  }
  return transaction;
};

const _requiresUserSubscription = (transaction) => {
  let userId;
  if (transaction.input.entityType === 'INDIVIDUAL') {
    userId = transaction.input.entityId;
  } else if (transaction.output.entityType === 'INDIVIDUAL') {
    userId = transaction.output.entityId;
  }
  if (userId && !Meteor.users.findOne({ _id: userId })) {
    return userId;
  }
  return false;
};

const _isWinningVote = (winningBallot, voterBallot) => {
  for (const i in voterBallot) {
    for (const k in winningBallot) {
      if (voterBallot[i]._id === winningBallot[k]._id) {
        return true;
      }
    }
  }
  return false;
};

const _buildFeed = (id, fields, instance, contract, noTitle) => {
  // added stuff
  // if (fields.kind === instance.data.options.kind) {
  const currentFeed = instance.feed.get();
  const post = fields;
  post._id = id;
  const userSubscriptionId = _requiresUserSubscription(post);
  if (userSubscriptionId) {
    getUser(userSubscriptionId);
  }

  const voteContract = _voteToContract(post, contract, noTitle, _isWinningVote(instance.data.winningBallot, post.condition.ballot), instance.openFeed);

  if (!currentFeed) {
    instance.feed.set([voteContract]);
  } else if (!here(voteContract, currentFeed)) {
    currentFeed.push(voteContract);
    instance.feed.set(_.uniq(currentFeed));
  }
  // }
};

Template.tally.onCreated(function () {
  Template.instance().feed = new ReactiveVar();
  Template.instance().contract = new ReactiveVar();
  Template.instance().openFeed = false;
  Template.instance().subscriptions = [];

  const instance = this;

  if (this.data.options.view === 'votes') {
    Meteor.call('getContract', this.data.options.keyword, function (error, result) {
      if (result) {
        instance.contract.set(result);
      } else if (error) {
        console.log(error);
      }
    });
  } else if (this.data.options.view === 'userVotes' || this.data.options.view === 'delegationVotes') {
    if (this.data.options.username) {
      Meteor.call('getUser', this.data.options.username, function (error, result) {
        if (result) {
          instance.contract.set(result);
        } else if (error) {
          console.log(error);
        }
      });
    } else if (this.data.options.userId) {
      instance.contract.set(Meteor.users.findOne({ _id: this.data.options.userId }));
    }
  } else if (this.data.options.view === 'lastVotes') {
    instance.openFeed = true;
  }

  this.subscription = instance.subscribe('tally', this.data.options);

  instance.autorun(function (computation) {
    const contract = instance.contract.get();
    let parameters;
    let dbQuery;
    let noTitle;

    if (contract || instance.openFeed) {
      if (instance.data.options.view === 'delegationVotes') {
        instance.openFeed = true;
      }
      parameters = query(Template.currentData().options);
      dbQuery = Transactions.find(parameters.find, parameters.options);
      noTitle = (Template.currentData().options.view === 'votes');
      if (contract) {
        Template.currentData().options.contractId = contract._id;
        Template.currentData().options.userId = contract._id;
      }
    }

    if (dbQuery) {
      if (instance.subscription.ready()) {
        Session.set('isLedgerReady', true);
        computation.stop();
      }
      instance.handle = dbQuery.observeChanges({
        addedBefore: (id, fields) => {
          _buildFeed(id, fields, instance, contract, noTitle);
        },
      });
    }
  });
});

Template.tally.helpers({
  vote() {
    console.log(this.options.kind);
    const feed = Template.instance().feed.get();
    console.log(feed);
    console.log('----');
    return Template.instance().feed.get();
  },
  ready() {
    if (Template.instance().openFeed) { return true; }
    return Template.instance().contract.get();
  },
});

Template.tally.onDestroyed(function () {
  if (this.handle) {
    this.handle.stop();
  }
  if (this.subscription) {
    this.subscription.stop();
  }
});
<commit_msg>specific case for multiple ledger visualization<commit_after>import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';

import { query } from '/lib/views';
import { here } from '/lib/utils';
import { Transactions } from '/imports/api/transactions/Transactions';
import { Contracts } from '/imports/api/contracts/Contracts';
import { getUser } from '/imports/ui/templates/components/identity/avatar/avatar';

import '/imports/ui/templates/widgets/tally/tally.html';

/**
* @summary translates data info about vote into a renderable contracts
* @param {object} post a transaction Object
*/
const _voteToContract = (post, contract, hidePost, winningBallot, openFeed) => {
  const transaction = {
    _id: post._id,
    ballot: post.condition.ballot,
    senderId: post.input.entityId,
    receiverId: post.output.entityId,
    isVote: true,
    hidePost,
    winningBallot,
    isRevoke: (post.input.entityType !== 'INDIVIDUAL'),
  };
  if (openFeed) {
    // for a feed in a general context (home page)
    if (post.kind === 'DELEGATION') {
      if (post.input.entityType === 'CONTRACT') {
        transaction.senderId = post.input.delegateId;
      } else if (post.output.entityType === 'CONTRACT') {
        transaction.receiverId = post.output.delegateId;
      }
      transaction.isVote = false;
    }
    transaction.contract = {
      timestamp: post.timestamp,
      kind: post.kind,
      wallet: {
        balance: post.output.quantity,
      },
      _id: post._id,
    };
  } else if (contract) {
    transaction.contract = {
      _id: contract._id,
      timestamp: post.timestamp,
      wallet: {
        balance: post.input.quantity,
      },
      title: contract.title,
      url: contract.url,
    };
  }
  return transaction;
};

const _requiresUserSubscription = (transaction) => {
  let userId;
  if (transaction.input.entityType === 'INDIVIDUAL') {
    userId = transaction.input.entityId;
  } else if (transaction.output.entityType === 'INDIVIDUAL') {
    userId = transaction.output.entityId;
  }
  if (userId && !Meteor.users.findOne({ _id: userId })) {
    return userId;
  }
  return false;
};

const _isWinningVote = (winningBallot, voterBallot) => {
  for (const i in voterBallot) {
    for (const k in winningBallot) {
      if (voterBallot[i]._id === winningBallot[k]._id) {
        return true;
      }
    }
  }
  return false;
};

const _buildFeed = (id, fields, instance, contract, noTitle) => {
  // added stuff
  // if (fields.kind === instance.data.options.kind) {
  const currentFeed = instance.feed.get();
  const post = fields;
  post._id = id;
  const userSubscriptionId = _requiresUserSubscription(post);
  if (userSubscriptionId) {
    getUser(userSubscriptionId);
  }

  const voteContract = _voteToContract(post, contract, noTitle, _isWinningVote(instance.data.winningBallot, post.condition.ballot), instance.openFeed);

  if (!currentFeed) {
    instance.feed.set([voteContract]);
  } else if (!here(voteContract, currentFeed)) {
    currentFeed.push(voteContract);
    instance.feed.set(_.uniq(currentFeed));
  }
  // }
};

Template.tally.onCreated(function () {
  Template.instance().feed = new ReactiveVar();
  Template.instance().contract = new ReactiveVar();
  Template.instance().openFeed = false;
  Template.instance().subscriptions = [];

  const instance = this;

  if (this.data.options.view === 'votes') {
    Meteor.call('getContract', this.data.options.keyword, function (error, result) {
      if (result) {
        instance.contract.set(result);
      } else if (error) {
        console.log(error);
      }
    });
  } else if (this.data.options.view === 'userVotes' || this.data.options.view === 'delegationVotes') {
    if (this.data.options.username) {
      Meteor.call('getUser', this.data.options.username, function (error, result) {
        if (result) {
          instance.contract.set(result);
        } else if (error) {
          console.log(error);
        }
      });
    } else if (this.data.options.userId) {
      instance.contract.set(Meteor.users.findOne({ _id: this.data.options.userId }));
    }
  } else if (this.data.options.view === 'lastVotes') {
    instance.openFeed = true;
  }

  this.subscription = instance.subscribe('tally', this.data.options);

  instance.autorun(function (computation) {
    const contract = instance.contract.get();
    let parameters;
    let dbQuery;
    let noTitle;

    if (contract || instance.openFeed) {
      if (instance.data.options.view === 'delegationVotes') {
        instance.openFeed = true;
      }
      parameters = query(Template.currentData().options);
      dbQuery = Transactions.find(parameters.find, parameters.options);
      noTitle = (Template.currentData().options.view === 'votes');
      if (contract) {
        Template.currentData().options.contractId = contract._id;
        Template.currentData().options.userId = contract._id;
      }
    }

    if (dbQuery) {
      if (instance.subscription.ready()) {
        Session.set('isLedgerReady', true);
        if (instance.data.options.view === 'userVotes' || instance.data.options.view === 'delegationVotes') {
          computation.stop();
        }
      }
      instance.handle = dbQuery.observeChanges({
        addedBefore: (id, fields) => {
          _buildFeed(id, fields, instance, contract, noTitle);
        },
      });
    }
  });
});

Template.tally.helpers({
  vote() {
    console.log(this.options.kind);
    const feed = Template.instance().feed.get();
    console.log(feed);
    console.log('----');
    return Template.instance().feed.get();
  },
  ready() {
    if (Template.instance().openFeed) { return true; }
    return Template.instance().contract.get();
  },
});

Template.tally.onDestroyed(function () {
  if (this.handle) {
    this.handle.stop();
  }
  if (this.subscription) {
    this.subscription.stop();
  }
});
<|endoftext|>


<commit_before>'use strict'

const electron = require('electron')
const menu = require('./menu')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const globalShortcut = electron.globalShortcut
const Menu = electron.Menu
const MenuItem = electron.MenuItem
const ipcMain = electron.ipcMain
const autoUpdater = electron.autoUpdater
const os = require('os')
const debounce = require('debounce')
const fs = require('fs')
const windowState = require('electron-window-state')
const contextMenu = require('electron-context-menu')
const shell = electron.shell

var mainWindow = null

const profile = process.env.SOUNDCLEOD_PROFILE
if (profile)
  app.setPath('userData', app.getPath('userData') + ' ' + profile)

var quitting = false

app.on('before-quit', function() {
  quitting = true
})

const shouldQuit = app.makeSingleInstance(() => {
  if (mainWindow) {
    if (mainWindow.isMinimized()) mainWindow.restore()
    mainWindow.show()
    mainWindow.focus()
  }
})

if (shouldQuit) app.quit()

app.on('activate', () => {
  if (mainWindow) mainWindow.show()
})

app.on('ready', function() {
  Menu.setApplicationMenu(menu)

  const mainWindowState = windowState({
    defaultWidth: 1024,
    defaultHeight: 640
  })

  mainWindow = new BrowserWindow({
    x: mainWindowState.x,
    y: mainWindowState.y,
    width: mainWindowState.width,
    height: mainWindowState.height,
    minWidth: 640,
    minHeight: 320,
    webPreferences: {
      nodeIntegration: false,
      preload: `${__dirname}/preload.js`
    }
  })

  mainWindowState.manage(mainWindow)

  mainWindow.on('close', (event) => {
    if (!quitting) {
      event.preventDefault()
      mainWindow.hide()
    }
  })

  mainWindow.on('closed', function() {
    mainWindow = null
  })

  function trigger(keyCode) {
    mainWindow.webContents.sendInputEvent({
      type: 'keyDown',
      keyCode
    })

    // Triggering keyUp immediately confuses SoundCloud
    setTimeout(() => {
      mainWindow.webContents.sendInputEvent({
        type: 'keyUp',
        keyCode
      })
    }, 50)
  }

  function goHome() {
    mainWindow.webContents.send('navigate', '/')
  }

  const playPause = () => trigger('Space')

  const nextTrack = () => trigger('J')

  const previousTrack = () => trigger('K')

  globalShortcut.register('MediaPlayPause', () => {
    playPause()
  })

  globalShortcut.register('MediaNextTrack', () => {
    nextTrack()
  })

  globalShortcut.register('MediaPreviousTrack', () => {
    previousTrack()
  })

  menu.events.on('home', () => {
    goHome()
  })

  menu.events.on('back', () => {
    mainWindow.webContents.goBack()
  })

  menu.events.on('forward', () => {
    mainWindow.webContents.goForward()
  })

  menu.events.on('main-window', () => {
    mainWindow.show()
  })

  require('electron').powerMonitor.on('suspend', () => {
    ipcMain.once('isPlaying', (_, isPlaying) => {
      if (isPlaying)
        playPause()
    })
    mainWindow.webContents.send('isPlaying')
  })

  const titleDebounceWaitMs = 200

  mainWindow.on('page-title-updated', debounce((_, title) => {
    var titleParts = title.split(' by ', 2)
    if (titleParts.length == 1)
      titleParts = title.split(' in ', 2)
    if (titleParts.length == 2) {
      // Title has " in " in it when not playing but on a playlis page
      ipcMain.once('isPlaying', (_, isPlaying) => {
        if (isPlaying)
          mainWindow.webContents.send('notification', titleParts[0], titleParts[1])
      })
      mainWindow.webContents.send('isPlaying')
    }
  }), titleDebounceWaitMs)

  function isLoginURL(url) {
    return [
      /^https:\/\/accounts\.google\.com.*/i
    ].some(re => url.match(re))
  }

  mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => {
    // Only allow login popups in SoundCleod, everything else open in external browser
    if (url && isLoginURL(url)) {
      // Do not copy these from mainWindow to login popups
      delete options.minWidth
      delete options.minHeight
      options.webPreferences = Object.assign({}, options.webPreferences, {
        preload: `${__dirname}/preload-popup.js`
      })
    } else {
      event.preventDefault()
      shell.openExternal(url)
    }
  })

  function isSoundCloudURL(url) {
    return [
      /^https?:\/\/soundcloud\.com.*/i
    ].some(re => url.match(re))
  }

  mainWindow.webContents.on('will-navigate', (event, url) => {
    if (url && !isSoundCloudURL(url)) {
      event.preventDefault()
      shell.openExternal(url)
    }
  })

  mainWindow.webContents.on('did-fail-load', (event, errorCode) => {
    const redirectErrorCode = -3
    if (errorCode != redirectErrorCode)
      mainWindow.loadURL(`file://${__dirname}/error.html`)
  })

  mainWindow.webContents.once('did-start-loading', () => {
    mainWindow.setTitle('Loading soundcloud.com...')
  })

  contextMenu({
    window: mainWindow,
    prepend: params => {
      if (params.mediaType == 'none')
        return [
          {
            label: 'Home',
            click() {
              goHome()
            }
          },
          {
            label: 'Go back',
            enabled: mainWindow.webContents.canGoBack(),
            click() {
              mainWindow.webContents.goBack()
            }
          },
          {
            label: 'Go forward',
            enabled: mainWindow.webContents.canGoForward(),
            click() {
              mainWindow.webContents.goForward()
            }
          }
        ]
    }
  })

  mainWindow.webContents.on('context-menu', event => {
    event.preventDefault()
    const menu = new Menu()
    menu.popup(mainWindow)
  })

  const dockMenu = new Menu()
  dockMenu.append(new MenuItem({
    label: 'Play/Pause',
    click() {
      playPause()
    }
  }))
  dockMenu.append(new MenuItem({
    label: 'Next',
    click() {
      nextTrack()
    }
  }))
  dockMenu.append(new MenuItem({
    label: 'Previous',
    click() {
      previousTrack()
    }
  }))

  app.dock.setMenu(dockMenu)

  mainWindow.loadURL('https://soundcloud.com')
})

function maybeStartAutoUpdater(callback) {
  if (process.env.NODE_ENV == 'development')
    console.log('Disabled automatic updates in development mode.')
  else
    // Test if updates can actually be installed, see also:
    // https://github.com/electron/electron/issues/7357
    fs.access(app.getPath('exe'), fs.constants.W_OK, err => {
      if (err && err.code == 'EROFS')
        console.log('Disabled automatic updates on a read-only file system.')
      else
        callback()
    })
}

maybeStartAutoUpdater(() => {
  const platform = os.platform() + '_' + os.arch()
  const version = app.getVersion()

  autoUpdater.setFeedURL(`https://soundcleod-updates.herokuapp.com/update/${platform}/${version}`)

  autoUpdater.on('checking-for-update', () => console.log('autoUpdater checking for update'))
  autoUpdater.on('update-available', () => console.log('autoUpdater update available'))
  autoUpdater.on('update-downloaded', () => console.log('autoUpdater update downloaded'))

  const oneHourInMs = 60 * 60 * 1000

  autoUpdater.on('update-not-available', () => {
    console.log('autoUpdater update not available')
    // Check again in an hour
    setTimeout(() => autoUpdater.checkForUpdates(), oneHourInMs)
  })

  autoUpdater.on('error', error => {
    console.error('autoUpdater error', error)
    // Check again in an hour
    setTimeout(() => autoUpdater.checkForUpdates(), oneHourInMs)
  })

  autoUpdater.checkForUpdates()
})
<commit_msg>Fix Facebook login again<commit_after>'use strict'

const electron = require('electron')
const menu = require('./menu')
const app = electron.app
const BrowserWindow = electron.BrowserWindow
const globalShortcut = electron.globalShortcut
const Menu = electron.Menu
const MenuItem = electron.MenuItem
const ipcMain = electron.ipcMain
const autoUpdater = electron.autoUpdater
const os = require('os')
const debounce = require('debounce')
const fs = require('fs')
const windowState = require('electron-window-state')
const contextMenu = require('electron-context-menu')
const shell = electron.shell

var mainWindow = null

const profile = process.env.SOUNDCLEOD_PROFILE
if (profile)
  app.setPath('userData', app.getPath('userData') + ' ' + profile)

var quitting = false

app.on('before-quit', function() {
  quitting = true
})

const shouldQuit = app.makeSingleInstance(() => {
  if (mainWindow) {
    if (mainWindow.isMinimized()) mainWindow.restore()
    mainWindow.show()
    mainWindow.focus()
  }
})

if (shouldQuit) app.quit()

app.on('activate', () => {
  if (mainWindow) mainWindow.show()
})

app.on('ready', function() {
  Menu.setApplicationMenu(menu)

  const mainWindowState = windowState({
    defaultWidth: 1024,
    defaultHeight: 640
  })

  mainWindow = new BrowserWindow({
    x: mainWindowState.x,
    y: mainWindowState.y,
    width: mainWindowState.width,
    height: mainWindowState.height,
    minWidth: 640,
    minHeight: 320,
    webPreferences: {
      nodeIntegration: false,
      preload: `${__dirname}/preload.js`
    }
  })

  mainWindowState.manage(mainWindow)

  mainWindow.on('close', (event) => {
    if (!quitting) {
      event.preventDefault()
      mainWindow.hide()
    }
  })

  mainWindow.on('closed', function() {
    mainWindow = null
  })

  function trigger(keyCode) {
    mainWindow.webContents.sendInputEvent({
      type: 'keyDown',
      keyCode
    })

    // Triggering keyUp immediately confuses SoundCloud
    setTimeout(() => {
      mainWindow.webContents.sendInputEvent({
        type: 'keyUp',
        keyCode
      })
    }, 50)
  }

  function goHome() {
    mainWindow.webContents.send('navigate', '/')
  }

  const playPause = () => trigger('Space')

  const nextTrack = () => trigger('J')

  const previousTrack = () => trigger('K')

  globalShortcut.register('MediaPlayPause', () => {
    playPause()
  })

  globalShortcut.register('MediaNextTrack', () => {
    nextTrack()
  })

  globalShortcut.register('MediaPreviousTrack', () => {
    previousTrack()
  })

  menu.events.on('home', () => {
    goHome()
  })

  menu.events.on('back', () => {
    mainWindow.webContents.goBack()
  })

  menu.events.on('forward', () => {
    mainWindow.webContents.goForward()
  })

  menu.events.on('main-window', () => {
    mainWindow.show()
  })

  require('electron').powerMonitor.on('suspend', () => {
    ipcMain.once('isPlaying', (_, isPlaying) => {
      if (isPlaying)
        playPause()
    })
    mainWindow.webContents.send('isPlaying')
  })

  const titleDebounceWaitMs = 200

  mainWindow.on('page-title-updated', debounce((_, title) => {
    var titleParts = title.split(' by ', 2)
    if (titleParts.length == 1)
      titleParts = title.split(' in ', 2)
    if (titleParts.length == 2) {
      // Title has " in " in it when not playing but on a playlis page
      ipcMain.once('isPlaying', (_, isPlaying) => {
        if (isPlaying)
          mainWindow.webContents.send('notification', titleParts[0], titleParts[1])
      })
      mainWindow.webContents.send('isPlaying')
    }
  }), titleDebounceWaitMs)

  function isLoginURL(url) {
    return [
      /^https:\/\/accounts\.google\.com.*/i,
      /^https:\/\/www.facebook.com\/dialog\/oauth.*/i
    ].some(re => url.match(re))
  }

  mainWindow.webContents.on('new-window', (event, url, frameName, disposition, options) => {
    // Only allow login popups in SoundCleod, everything else open in external browser
    if (url && isLoginURL(url)) {
      // Do not copy these from mainWindow to login popups
      delete options.minWidth
      delete options.minHeight
      options.webPreferences = Object.assign({}, options.webPreferences, {
        preload: `${__dirname}/preload-popup.js`
      })
    } else {
      event.preventDefault()
      shell.openExternal(url)
    }
  })

  function isSoundCloudURL(url) {
    return [
      /^https?:\/\/soundcloud\.com.*/i
    ].some(re => url.match(re))
  }

  mainWindow.webContents.on('will-navigate', (event, url) => {
    if (url && !isSoundCloudURL(url) && !isLoginURL(url)) {
      event.preventDefault()
      shell.openExternal(url)
    }
  })

  mainWindow.webContents.on('did-fail-load', (event, errorCode) => {
    const redirectErrorCode = -3
    if (errorCode != redirectErrorCode)
      mainWindow.loadURL(`file://${__dirname}/error.html`)
  })

  mainWindow.webContents.once('did-start-loading', () => {
    mainWindow.setTitle('Loading soundcloud.com...')
  })

  contextMenu({
    window: mainWindow,
    prepend: params => {
      if (params.mediaType == 'none')
        return [
          {
            label: 'Home',
            click() {
              goHome()
            }
          },
          {
            label: 'Go back',
            enabled: mainWindow.webContents.canGoBack(),
            click() {
              mainWindow.webContents.goBack()
            }
          },
          {
            label: 'Go forward',
            enabled: mainWindow.webContents.canGoForward(),
            click() {
              mainWindow.webContents.goForward()
            }
          }
        ]
    }
  })

  mainWindow.webContents.on('context-menu', event => {
    event.preventDefault()
    const menu = new Menu()
    menu.popup(mainWindow)
  })

  const dockMenu = new Menu()
  dockMenu.append(new MenuItem({
    label: 'Play/Pause',
    click() {
      playPause()
    }
  }))
  dockMenu.append(new MenuItem({
    label: 'Next',
    click() {
      nextTrack()
    }
  }))
  dockMenu.append(new MenuItem({
    label: 'Previous',
    click() {
      previousTrack()
    }
  }))

  app.dock.setMenu(dockMenu)

  mainWindow.loadURL('https://soundcloud.com')
})

function maybeStartAutoUpdater(callback) {
  if (process.env.NODE_ENV == 'development')
    console.log('Disabled automatic updates in development mode.')
  else
    // Test if updates can actually be installed, see also:
    // https://github.com/electron/electron/issues/7357
    fs.access(app.getPath('exe'), fs.constants.W_OK, err => {
      if (err && err.code == 'EROFS')
        console.log('Disabled automatic updates on a read-only file system.')
      else
        callback()
    })
}

maybeStartAutoUpdater(() => {
  const platform = os.platform() + '_' + os.arch()
  const version = app.getVersion()

  autoUpdater.setFeedURL(`https://soundcleod-updates.herokuapp.com/update/${platform}/${version}`)

  autoUpdater.on('checking-for-update', () => console.log('autoUpdater checking for update'))
  autoUpdater.on('update-available', () => console.log('autoUpdater update available'))
  autoUpdater.on('update-downloaded', () => console.log('autoUpdater update downloaded'))

  const oneHourInMs = 60 * 60 * 1000

  autoUpdater.on('update-not-available', () => {
    console.log('autoUpdater update not available')
    // Check again in an hour
    setTimeout(() => autoUpdater.checkForUpdates(), oneHourInMs)
  })

  autoUpdater.on('error', error => {
    console.error('autoUpdater error', error)
    // Check again in an hour
    setTimeout(() => autoUpdater.checkForUpdates(), oneHourInMs)
  })

  autoUpdater.checkForUpdates()
})
<|endoftext|>