<commit_before>"use strict";
const utils = require("./utils");
const financials = require("./financials");
const constants = require("./constants");
var colors = require("colors");

// utils.list_files(OUTPUT_FOLDER)
//     .then(console.log);

const constructFilePath = (date) => {
    return Promise.resolve(constants.EXPORT_FOLDER + date + ".csv");
};

const computeChangesEtf = (resultList) => {
    let cheaperList = [];
    let moreExpensiveList = [];
    let tickerList = resultList[0].reduce( (total, elt) => {
        total.push(elt.name);
        return total;
    }, []);
    for (const ticker of tickerList) {
        // TODO should be compared over tickers, but were not available in oldest datasets
        let old = resultList[0].find(x => x.name === ticker);
        let n = resultList[1].find(x => x.name === ticker);
        if (old !== undefined && n !== undefined) {
            // let earningsUpdate = financials.haveEarningsChanged(old.price, old.pe, n.price, n.pe);
            // console.log(ticker + " " + priceVariation);
            const oldValue = parseFloat(old[CRITERIA]);
            const newValue = parseFloat(n[CRITERIA]);
            let listToAppend;
            if (!financials.areFloatEqual(oldValue, newValue)) {
                let variation = newValue / oldValue;
                if (variation < 1) {
                    listToAppend = cheaperList;
                }
                else {
                    listToAppend = moreExpensiveList;
                }
                listToAppend.push({
                        old: old,
                        n: n,
                        variation: variation
                    });
                }
            }
        }
    cheaperList.sort( (a, b) => {
        return a.variation - b.variation;
    });
    moreExpensiveList.sort( (a, b) => {
        return b.variation - a.variation;
    });
    return {
        cheaperList: cheaperList,
        moreExpensiveList: moreExpensiveList,
        criteria: CRITERIA
    };
};

const displaySubList = (subList, criteria) => {
    let old, n, variation;
    for (let e of subList) {
        ({ old, n, variation } = e);
        let priceVariation = utils.prettyPrintPercentage(n.price / old.price);
        console.log(n.name + " " + priceVariation);
        console.log(old[criteria] + " => " + n[criteria]);
        if (variation < 1) {
            console.log(`↘ ${utils.prettyPrintPercentage(variation)}`.green);
        }
        else {
            console.log(`↗ ${utils.prettyPrintPercentage(variation)}`.red);
        }
    }
};

const displayResults = (res) => {
    let cheaperList, moreExpensiveList, criteria;
    ({ cheaperList, moreExpensiveList, criteria } = res);

    console.log(`Based on ${criteria}`);
    if (cheaperList.length > 0) {
        console.log("============================\nCheaper\n");
    displaySubList(cheaperList, criteria);
    }
    if (moreExpensiveList.length > 0) {
        console.log("============================\nMore expensive");
    displaySubList(moreExpensiveList, criteria);
    }
};

let path = ["test-2017-10-29", "test-2017-10-30"];
path = ["2017-09-24", "2017-11-4"];
Promise.all(path
    .map((x) => constructFilePath(x)
        .then(utils.readFromCsv)))
    .then(computeChangesEtf)
    .then(displayResults)
    .catch(console.err);<commit_msg>CLI for analyzer<commit_after>"use strict";
const utils = require("./utils");
const financials = require("./financials");
const constants = require("./constants");
const cli = require("cli");
var colors = require("colors");

const cliArgs = cli.parse({
    criteria: [ "c", "Criteria to be used for filtering/ordering", "string", "pe" ],  //     --work STRING What kind of work to do
    begin: [ "b", "First date", "string"],//, "2017-09-24" ],
    end: [ "e", "End date", "string"]//, "2017-11-25" ],
});
let path = [cliArgs.begin, cliArgs.end];
const CRITERIA = cliArgs.criteria;
// utils.list_files(OUTPUT_FOLDER)
//     .then(console.log);

const constructFilePath = (date) => {
    return Promise.resolve(constants.EXPORT_FOLDER + date + ".csv");
};

const computeChangesEtf = (resultList) => {
    let cheaperList = [];
    let moreExpensiveList = [];
    let tickerList = resultList[0].reduce( (total, elt) => {
        total.push(elt.name);
        return total;
    }, []);
    for (const ticker of tickerList) {
        // TODO should be compared over tickers, but were not available in oldest datasets
        let old = resultList[0].find(x => x.name === ticker);
        let n = resultList[1].find(x => x.name === ticker);
        if (old !== undefined && n !== undefined) {
            // let earningsUpdate = financials.haveEarningsChanged(old.price, old.pe, n.price, n.pe);
            // console.log(ticker + " " + priceVariation);
            const oldValue = parseFloat(old[CRITERIA]);
            const newValue = parseFloat(n[CRITERIA]);
            let listToAppend;
            if (!financials.areFloatEqual(oldValue, newValue)) {
                let variation = newValue / oldValue;
                if (variation < 1) {
                    listToAppend = cheaperList;
                }
                else {
                    listToAppend = moreExpensiveList;
                }
                listToAppend.push({
                        old: old,
                        n: n,
                        variation: variation
                    });
                }
            }
        }
    cheaperList.sort( (a, b) => {
        return a.variation - b.variation;
    });
    moreExpensiveList.sort( (a, b) => {
        return b.variation - a.variation;
    });
    return {
        cheaperList: cheaperList,
        moreExpensiveList: moreExpensiveList,
        criteria: CRITERIA
    };
};

const displaySubList = (subList, criteria) => {
    let old, n, variation;
    for (let e of subList) {
        ({ old, n, variation } = e);
        let priceVariation = utils.prettyPrintPercentage(n.price / old.price);
        console.log(n.name + " " + priceVariation);
        console.log(old[criteria] + " => " + n[criteria]);
        if (variation < 1) {
            console.log(`↘ ${utils.prettyPrintPercentage(variation)}`.green);
        }
        else {
            console.log(`↗ ${utils.prettyPrintPercentage(variation)}`.red);
        }
    }
};

const displayResults = (res) => {
    let cheaperList, moreExpensiveList, criteria;
    ({ cheaperList, moreExpensiveList, criteria } = res);

    console.log(`Based on ${criteria}`);
    if (cheaperList.length > 0) {
        console.log("============================\nCheaper\n");
    displaySubList(cheaperList, criteria);
    }
    if (moreExpensiveList.length > 0) {
        console.log("============================\nMore expensive");
    displaySubList(moreExpensiveList, criteria);
    }
};

Promise.all(path
    .map((x) => constructFilePath(x)
        .then(utils.readFromCsv)))
    .then(computeChangesEtf)
    .then(displayResults)
    .catch(console.err);<|endoftext|>


<commit_before>//Pure JS based composition
define.class('$server/composition', function($ui$, screen, view, button,label, speakergrid){

	define.class(this, "popupmenu", function($ui$, view, label, button){
		this.bgcolor = "gray"
		this.flexdirection = "row"
		this.attributes = {
				menus:[
					{name:"File", commands:[
							{name:"New project with a long name", action:function(){console.log("new project with a long name") ;}},
							{name:"Open", action:function(){console.log("Open") ;}},
							{name:"Save", action:function(){console.log("Save") ;}}
						]
					}
					,{name:"Edit", commands:[
							{name:"New project with a long name", action:function(){console.log("new project with a long name") ;}},
							{name:"Open", action:function(){console.log("Open") ;}},
							{name:"Save", action:function(){console.log("Save") ;}}
						]
					}
			]}

		this.render = function(){
			if (!this.menus) return [];

			var mres = []

			for(var m in this.menus){
				var res = [];
				var menu = this.menus[m];
				console.log("menu:" , menu);
				mres.push(button({ text:menu.name, menucommands: menu.commands, click: function()
				{
					// lets open a modal dialog
					var res = [];
					console.log("full menucommands array", this.menucommands);
					for(var a in this.menucommands){
						var c = this.menucommands[a];
						console.log("menucommand: ", c);
						res.push(button({text:c.name,clickaction: c.action, click:function(){if(this.clickaction) this.clickaction(); this.closeModal(true);}, margin:1}))
					}

					this.screen.openModal(
						view({bg:false,flexdirection:"column",
							miss:function(){
								this.closeModal(false)
							},
							init:function(){
								console.log('here')
							},
							pos:[0,0],
							size:[300,300],position:'absolute'
						}, res)
					).then(function(result){
						console.log(result)
					})

				}}));
			}
			return mres;
		}
	})

	this.justifycontent = "center" ;
	this.alignitems = "center"

	this.render = function(){ return [
		screen({clearcolor:vec4('black')},
			view({flex:1, bg:'false'},
				speakergrid({ }
				,view({bgcolor:vec4(0,0.1,0.2,0.8) , flexdirection:"column"},view({bg:false},this.popupmenu({position:"relative",margin:10,flex:0}))))
			)
		)
	]}
})<commit_msg>Menu progress<commit_after>//Pure JS based composition
define.class('$server/composition', function($ui$, screen, view, button,label, speakergrid){

	define.class(this, "popupmenu", function($ui$, view, label, button){
		this.bgcolor = "gray"
		this.flexdirection = "row"
		this.attributes = {
				menus:[
					{name:"File", commands:[
							{name:"New project", action:function(){console.log("new project with a long name") ;}},
							{name:"Open", action:function(){console.log("Open") ;}},
							{name:"Save", action:function(){console.log("Save") ;}}
						]
					}
					,{name:"Edit", commands:[
							{name:"Undo", action:function(){console.log("Undo") ;}},
							{name:"Redo", action:function(){console.log("Redo") ;}},
							{name:"Cut", action:function(){console.log("Cut") ;}},
							{name:"Copy", action:function(){console.log("Copy") ;}},
							{name:"Paste", action:function(){console.log("Paste") ;}}
						]
					}
			]}

		this.render = function(){
			if (!this.menus) return [];

			var mres = []

			for(var m in this.menus){
				var res = [];
				var menu = this.menus[m];
				console.log("menu:" , menu);
				mres.push(button({ text:menu.name, menucommands: menu.commands, click: function()
				{
					// lets open a modal dialog
					var res = [];
					console.log("full menucommands array", this.menucommands);
					for(var a in this.menucommands){
						var c = this.menucommands[a];
						console.log("menucommand: ", c);
						res.push(button({text:c.name,buttoncolor1:"#505050",borderwidth:0,hovercolor1:"#606060",hovercolor2:"#606060", buttoncolor2:"#505050",   clickaction: c.action, click:function(){if(this.clickaction) this.clickaction(); this.closeModal(true);}, margin:1}))
					}

					this.screen.openModal(
						view({bgcolor:"#505050",flexdirection:"column",
							miss:function(){
								this.closeModal(false)
							},
							init:function(){
								console.log('here')
							},
							pos:[this.layout.absx,this.layout.absy + this.layout.height+2],
							size:[300,NaN],position:'absolute'
						}, res)
					).then(function(result){
						console.log(result)
					})

				}}));
			}
			return mres;
		}
	})

	this.justifycontent = "center" ;
	this.alignitems = "center"

	this.render = function(){ return [
		screen({clearcolor:vec4('black')},
			view({flex:1, bg:'false'},
				speakergrid({ }
				,view({bgcolor:vec4(0,0.1,0.2,0.8) , flexdirection:"column"},view({bg:false},this.popupmenu({position:"relative",margin:10,flex:0}))))
			)
		)
	]}
})<|endoftext|>


<commit_before>import * as React from 'react';
import { View } from 'react-native';

class SharedElement extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.state = {url: this.getStateNavigator().stateContext.url};
        this.register = this.register.bind(this);
    }
    static contextTypes = {
        stateNavigator: React.PropTypes.object,
        registerSharedElement: React.PropTypes.func
    }
    getStateNavigator() {
        return this.props.stateNavigator || this.context.stateNavigator;
    }
    register() {
        this.component.measure((ox, oy, w, h, x, y) => {
            var {url} = this.state;
            var {name, children} = this.props;
            var {registerSharedElement} = this.context;
            registerSharedElement(url, name, children, {w, h, x, y});
        });
    }
    render() {
        return React.cloneElement(this.props.children, {
            onLayout: this.register,
            ref: comp => {this.component = comp}
        });
    }
}

export default SharedElement;

<commit_msg>Registered on layout only if current state<commit_after>import * as React from 'react';
import { View } from 'react-native';

class SharedElement extends React.Component {
    constructor(props, context) {
        super(props, context);
        this.state = {url: this.getStateNavigator().stateContext.url};
        this.register = this.register.bind(this);
    }
    static contextTypes = {
        stateNavigator: React.PropTypes.object,
        registerSharedElement: React.PropTypes.func
    }
    getStateNavigator() {
        return this.props.stateNavigator || this.context.stateNavigator;
    }
    componentDidMount() {
        var stateNavigator = this.getStateNavigator();
        stateNavigator.onNavigate(this.register);
    }
    componentWillUnmount() {
        this.getStateNavigator().offNavigate(this.register);
    }
    register() {
        var {url} = this.state;
        if (url === this.getStateNavigator().stateContext.url) {
            this.component.measure((ox, oy, w, h, x, y) => {
                var {name, children} = this.props;
                var {registerSharedElement} = this.context;
                registerSharedElement(url, name, children, {w, h, x, y});
            });
        }
    }
    render() {
        return React.cloneElement(this.props.children, {
            onLayout: this.register,
            ref: comp => {this.component = comp}
        });
    }
}

export default SharedElement;

<|endoftext|>


<commit_before>function debug(message)
{
    if(paymillcheckout.debug){
        console.log("[" + getPayment() + "] " + message);
    }
}

function getPayment()
{
    return paymillcheckout.tokenPayment;
}

function hasDummyData()
{
    if (getPayment() === 'paymillcc') { //If CC
        if (!paymillcheckout.iframe.active) { //if not iframe solutin
            var cardNumber = $('#card-number').val();
            var validMonth = $('#card-expiry-month').val();
            var validYear = $('#card-expiry-year').val();

            debug(cardNumber);
            debug(validMonth);
            debug(validYear);

            if ((cardNumber === "" || validMonth === "" || validYear === "") || (paymillcheckout.fastcheckout.creditcard.cardnumber != cardNumber) || (paymillcheckout.fastcheckout.creditcard.month != validMonth) || (paymillcheckout.fastcheckout.creditcard.year != validYear)) {
                debug("Creditcard information found. New Information will be used. Token should be getting generated.");
                return false;
            }
        } else if (paymillcheckout.fastcheckout.changed) {
            return false;
        }
    }

    if (getPayment() === 'paymilldebit') {
        var iban = $('#paymill_iban').val();
        var bic = $('#paymill_bic').val();
        if ((iban === "" || bic === "") || (paymillcheckout.fastcheckout.directdebit.accountnumber !== iban) || (paymillcheckout.fastcheckout.directdebit.bankcode !== bic)) {
            debug("Direct Debit information found. New Information will be used. Token should be getting generated.");
            return false;
        }
    }
    debug("Fast Checkout Data found and not altered. Will process with given data. Validation will be skipped.");
    return true;
}

function validate()
{
    debug("Paymill handler triggered");
    var errorsCc = $("#errorsCc");
    errorsCc.parents('.error').hide();
    errorsCc.html("");
    var errorsElv = $("#errorsElv");
    errorsElv.parents('.error').hide();
    errorsElv.html("");
    var result = true;
    if (getPayment() === 'paymillcc') { //If CC
        if (!paymillcheckout.iframe.active) { // if not iframe solution
            if (!paymill.validateHolder($('#card-holder').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cardholder+"
");
                result = false;
            }
            if (!paymill.validateCardNumber($('#card-number').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cardnumber+"
");
                result = false;
            }
            if (!paymill.validateCvc($('#card-cvc').val())) {
                if (paymillcheckout.validateCvc) {
                    errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cvc+"
");
                    result = false;
                }
            }
            if (/^\d\d$/.test($('#card-expiry-year').val())) {
                $('#card-expiry-year').val("20" + $('#card-expiry-year').val());
            }
            if (!paymill.validateExpiry($('#card-expiry-month').val(), $('#card-expiry-year').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.expirydate+"
");
                result = false;
            }
            if (!result) {
                errorsCc.parents('.error').show();
            } else {
                debug("Validations successful");
            }
        } else {
            result = true;
            debug("No validation, because of iFrame Solution.");
        }
    }

    if (getPayment() === 'paymilldebit') { //If ELV
        if (!paymill.validateHolder($('#paymill_accountholder').val())) {
            errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.accountholder+"
");
            result = false;
        }
        if (isSepa()) {
            var iban = new Iban();
            if (!iban.validate($('#paymill_iban').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.iban+"
");
                result = false;
            }

            if ($('#paymill_bic').val() === '') {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.bic+"
");
                result = false;
            }
        } else {
            if (!paymill.validateAccountNumber($('#paymill_iban').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.accountnumber+"
");
                result = false;
            }

            if (!paymill.validateBankCode($('#paymill_bic').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.bankcode+"
");
                result = false;
            }
        }
        if (!result) {
            errorsElv.parents('.error').show();
        } else {
            debug("Validations successful");
        }
    }
    return result;
}

function paymillResponseHandler(error, result)
{
    $('button[type="submit"]').removeAttr("disabled");
    debug("Started Paymill response handler");
    if (error) {
        errorText = paymillcheckout.errormessages.bridge[error.apierror];
        debug(errorText);
        alert(errorText);
    } else {
        debug("Received token from Paymill API: " + result.token);
        paymillSubmitForm(result.token);
    }
}

function paymillSubmitForm(token){
    var form = $('#confirm--form');
    var name;
    if(getPayment() === 'paymillcc'){
        name = $('#card-holder').val();
    }else{
        name = $('#paymill_accountholder').val();
    }
    form.append("<input type='hidden' name='paymillToken' value='" + token + "'/>");
    form.append("<input type='hidden' name='paymillName' value='" + name + "'/>");
    form.submit();
}

function isSepa() {
    var reg = new RegExp(/^\D\D/);
    return reg.test($('#paymill_iban').val());
}

$(document).ready(function ()
{
    var paymill_form_id = "payment_mean{$payment_mean.id}";
    $('#card-number').keyup(function ()
    {
        $("#card-number")[0].className = $("#card-number")[0].className.replace(/paymill-card-number-.*/g, '');
        var detector = new BrandDetection();
        var brand = detector.detect($('#card-number').val());

        if (detector.validate($('#card-number').val())) {
            suffix = '';
        } else {
            suffix = '-temp';
        }
        if ($.inArray(brand, paymillcheckout.activeBrands) !== -1) {
            $('#card-number').addClass("paymill-card-number-" + brand + suffix);
        }
    });

    $('button[type="submit"][form="confirm--form"]').click(function ()
    {
        debug('Event triggered');
        /* prevend token generation when token already exsist */
        if ($("input[type='checkbox'][name='paymillToken']").length) {
            return true;
        }
        $(this).attr("disabled","disabled");
        debug('Check for FastCheckout data.');
        if (hasDummyData()) {
            debug('Proceed Fastcheckout');
            paymillSubmitForm('NoTokenRequired');
        } else {
            debug('Validate data');
            if (validate()) {
                try {
                    if (getPayment() === 'paymillcc') { //If CC
                        if (!paymillcheckout.iframe.active) { //if not iFrame Solution
                            if (paymillcheckout.validateCvc) {
                                paymill.createToken({
                                    number: $('#card-number').val(),
                                    cardholder: $('#card-holder').val(),
                                    exp_month: $('#card-expiry-month').val(),
                                    exp_year: $('#card-expiry-year').val(),
                                    cvc: $('#card-cvc').val(),
                                    amount_int: paymillcheckout.tokenAmount,
                                    currency: paymillcheckout.tokenCurrency
                                }, paymillResponseHandler);
                            } else {
                                cvcInput = $('#card-cvc').val();
                                paymill.createToken({
                                    number: $('#card-number').val(),
                                    cardholder: $('#card-holder').val(),
                                    exp_month: $('#card-expiry-month').val(),
                                    exp_year: $('#card-expiry-year').val(),
                                    cvc: cvcInput === "" ? "000" : cvcInput,
                                    amount_int: paymillcheckout.tokenAmount,
                                    currency: paymillcheckout.tokenCurrency
                                }, paymillResponseHandler);
                            }
                        } else {
                            paymill.createTokenViaFrame({
                                amount_int: paymillcheckout.tokenAmount,
                                currency: paymillcheckout.tokenCurrency
                            }, paymillResponseHandler);
                        }
                    }
                    if (getPayment() === 'paymilldebit') { //If ELV
                        if (isSepa()) {
                            paymill.createToken({
                                iban: $('#paymill_iban').val(),
                                bic: $('#paymill_bic').val(),
                                accountholder: $('#paymill_accountholder').val()
                            }, paymillResponseHandler);
                        } else {
                            paymill.createToken({
                                number: $('#paymill_iban').val(),
                                bank: $('#paymill_bic').val(),
                                accountholder: $('#paymill_accountholder').val()
                            }, paymillResponseHandler);
                        }
                    }
                } catch (e) {
                    alert("Ein Fehler ist aufgetreten: " + e);
                    $(this).removeAttr("disabled");
                }
            } else {
                $(this).removeAttr("disabled");
                if (getPayment() === 'paymillcc') {
                    $('html, body').animate({
                        scrollTop: $("#errorsCc").offset().top - 100
                    }, 1000);
                }
                if (getPayment() === 'paymilldebit') {
                    $('html, body').animate({
                        scrollTop: $("#errorsElv").offset().top - 100
                    }, 1000);
                }
            }
        }
        return false;
    });

    $('#paymillFastCheckoutIframeChange').click(function (event) {
        $("#paymillFastCheckoutTable").remove();
        paymillEmbedFrame();
    });
});<commit_msg>PSW-131 - fixed countinously loading issue<commit_after>function debug(message)
{
    if(paymillcheckout.debug){
        console.log("[" + getPayment() + "] " + message);
    }
}

function getPayment()
{
    return paymillcheckout.tokenPayment;
}

function hasDummyData()
{
    if (getPayment() === 'paymillcc') { //If CC
        if (!paymillcheckout.iframe.active) { //if not iframe solutin
            var cardNumber = $('#card-number').val();
            var validMonth = $('#card-expiry-month').val();
            var validYear = $('#card-expiry-year').val();

            debug(cardNumber);
            debug(validMonth);
            debug(validYear);

            if ((cardNumber === "" || validMonth === "" || validYear === "") || (paymillcheckout.fastcheckout.creditcard.cardnumber != cardNumber) || (paymillcheckout.fastcheckout.creditcard.month != validMonth) || (paymillcheckout.fastcheckout.creditcard.year != validYear)) {
                debug("Creditcard information found. New Information will be used. Token should be getting generated.");
                return false;
            }
        } else if (paymillcheckout.fastcheckout.changed) {
            return false;
        }
    }

    if (getPayment() === 'paymilldebit') {
        var iban = $('#paymill_iban').val();
        var bic = $('#paymill_bic').val();
        if ((iban === "" || bic === "") || (paymillcheckout.fastcheckout.directdebit.accountnumber !== iban) || (paymillcheckout.fastcheckout.directdebit.bankcode !== bic)) {
            debug("Direct Debit information found. New Information will be used. Token should be getting generated.");
            return false;
        }
    }
    debug("Fast Checkout Data found and not altered. Will process with given data. Validation will be skipped.");
    return true;
}

function validate()
{
    debug("Paymill handler triggered");
    var errorsCc = $("#errorsCc");
    errorsCc.parents('.error').hide();
    errorsCc.html("");
    var errorsElv = $("#errorsElv");
    errorsElv.parents('.error').hide();
    errorsElv.html("");
    var result = true;
    if (getPayment() === 'paymillcc') { //If CC
        if (!paymillcheckout.iframe.active) { // if not iframe solution
            if (!paymill.validateHolder($('#card-holder').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cardholder+"
");
                result = false;
            }
            if (!paymill.validateCardNumber($('#card-number').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cardnumber+"
");
                result = false;
            }
            if (!paymill.validateCvc($('#card-cvc').val())) {
                if (paymillcheckout.validateCvc) {
                    errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.cvc+"
");
                    result = false;
                }
            }
            if (/^\d\d$/.test($('#card-expiry-year').val())) {
                $('#card-expiry-year').val("20" + $('#card-expiry-year').val());
            }
            if (!paymill.validateExpiry($('#card-expiry-month').val(), $('#card-expiry-year').val())) {
                errorsCc.append("
"+paymillcheckout.errormessages.validation.creditcard.expirydate+"
");
                result = false;
            }
            if (!result) {
                errorsCc.parents('.error').show();
            } else {
                debug("Validations successful");
            }
        } else {
            result = true;
            debug("No validation, because of iFrame Solution.");
        }
    }

    if (getPayment() === 'paymilldebit') { //If ELV
        if (!paymill.validateHolder($('#paymill_accountholder').val())) {
            errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.accountholder+"
");
            result = false;
        }
        if (isSepa()) {
            var iban = new Iban();
            if (!iban.validate($('#paymill_iban').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.iban+"
");
                result = false;
            }

            if ($('#paymill_bic').val() === '') {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.bic+"
");
                result = false;
            }
        } else {
            if (!paymill.validateAccountNumber($('#paymill_iban').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.accountnumber+"
");
                result = false;
            }

            if (!paymill.validateBankCode($('#paymill_bic').val())) {
                errorsElv.append("
"+paymillcheckout.errormessages.validation.directdebit.bankcode+"
");
                result = false;
            }
        }
        if (!result) {
            errorsElv.parents('.error').show();
        } else {
            debug("Validations successful");
        }
    }
    return result;
}

function paymillResponseHandler(error, result)
{
    $('button[type="submit"]').removeAttr("disabled");
    debug("Started Paymill response handler");
    if (error) {
        errorText = paymillcheckout.errormessages.bridge[error.apierror];
        debug(errorText);
        alert(errorText);
    } else {
        debug("Received token from Paymill API: " + result.token);
        paymillSubmitForm(result.token);
    }
}

function paymillSubmitForm(token){
    var form = $('#confirm--form');
    var name;
    if(getPayment() === 'paymillcc'){
        name = $('#card-holder').val();
    }else{
        name = $('#paymill_accountholder').val();
    }
    form.append("<input type='hidden' name='paymillToken' value='" + token + "'/>");
    form.append("<input type='hidden' name='paymillName' value='" + name + "'/>");
    form.submit();
}

function isSepa() {
    var reg = new RegExp(/^\D\D/);
    return reg.test($('#paymill_iban').val());
}

$(document).ready(function ()
{
    var paymill_form_id = "payment_mean{$payment_mean.id}";
    $('#card-number').keyup(function ()
    {
        $("#card-number")[0].className = $("#card-number")[0].className.replace(/paymill-card-number-.*/g, '');
        var detector = new BrandDetection();
        var brand = detector.detect($('#card-number').val());

        if (detector.validate($('#card-number').val())) {
            suffix = '';
        } else {
            suffix = '-temp';
        }
        if ($.inArray(brand, paymillcheckout.activeBrands) !== -1) {
            $('#card-number').addClass("paymill-card-number-" + brand + suffix);
        }
    });

    $('button[type="submit"][form="confirm--form"]').click(function ()
    {
        debug('Event triggered');
        /* prevend token generation when token already exsist */
        if ($("input[type='checkbox'][name='paymillToken']").length) {
            return true;
        }

        /* prevend token generation when agb hasn't been accepted */
        if ($("input[type='checkbox'][name='sAGB']").length) {
            if ($("input[type='checkbox'][name='sAGB']").attr('checked') !== "checked") {
                event.preventDefault();
            }
        }

        $(this).attr("disabled","disabled");
        debug('Check for FastCheckout data.');
        if (hasDummyData()) {
            debug('Proceed Fastcheckout');
            paymillSubmitForm('NoTokenRequired');
        } else {
            debug('Validate data');
            if (validate()) {
                try {
                    if (getPayment() === 'paymillcc') { //If CC
                        if (!paymillcheckout.iframe.active) { //if not iFrame Solution
                            if (paymillcheckout.validateCvc) {
                                paymill.createToken({
                                    number: $('#card-number').val(),
                                    cardholder: $('#card-holder').val(),
                                    exp_month: $('#card-expiry-month').val(),
                                    exp_year: $('#card-expiry-year').val(),
                                    cvc: $('#card-cvc').val(),
                                    amount_int: paymillcheckout.tokenAmount,
                                    currency: paymillcheckout.tokenCurrency
                                }, paymillResponseHandler);
                            } else {
                                cvcInput = $('#card-cvc').val();
                                paymill.createToken({
                                    number: $('#card-number').val(),
                                    cardholder: $('#card-holder').val(),
                                    exp_month: $('#card-expiry-month').val(),
                                    exp_year: $('#card-expiry-year').val(),
                                    cvc: cvcInput === "" ? "000" : cvcInput,
                                    amount_int: paymillcheckout.tokenAmount,
                                    currency: paymillcheckout.tokenCurrency
                                }, paymillResponseHandler);
                            }
                        } else {
                            paymill.createTokenViaFrame({
                                amount_int: paymillcheckout.tokenAmount,
                                currency: paymillcheckout.tokenCurrency
                            }, paymillResponseHandler);
                        }
                    }
                    if (getPayment() === 'paymilldebit') { //If ELV
                        if (isSepa()) {
                            paymill.createToken({
                                iban: $('#paymill_iban').val(),
                                bic: $('#paymill_bic').val(),
                                accountholder: $('#paymill_accountholder').val()
                            }, paymillResponseHandler);
                        } else {
                            paymill.createToken({
                                number: $('#paymill_iban').val(),
                                bank: $('#paymill_bic').val(),
                                accountholder: $('#paymill_accountholder').val()
                            }, paymillResponseHandler);
                        }
                    }
                } catch (e) {
                    alert("Ein Fehler ist aufgetreten: " + e);
                    $(this).removeAttr("disabled");
                }
            } else {
                $(this).removeAttr("disabled");
                if (getPayment() === 'paymillcc') {
                    $('html, body').animate({
                        scrollTop: $("#errorsCc").offset().top - 100
                    }, 1000);
                }
                if (getPayment() === 'paymilldebit') {
                    $('html, body').animate({
                        scrollTop: $("#errorsElv").offset().top - 100
                    }, 1000);
                }
            }
        }
        return false;
    });

    $('#paymillFastCheckoutIframeChange').click(function (event) {
        $("#paymillFastCheckoutTable").remove();
        paymillEmbedFrame();
    });
});<|endoftext|>


<commit_before>/*
 * Copyright (C) 2015 Actor LLC. <https://actor.im>
 */

import _ from 'lodash';

import React from 'react';
import classnames from 'classnames';
import ReactMixin from 'react-mixin';
import addons from 'react/addons';
const {addons: { PureRenderMixin }} = addons;

import ActorClient from 'utils/ActorClient';
import Inputs from 'utils/Inputs';

import { KeyCodes } from 'constants/ActorAppConstants';

import MessageActionCreators from 'actions/MessageActionCreators';
import ComposeActionCreators from 'actions/ComposeActionCreators';

import GroupStore from 'stores/GroupStore';
import PreferencesStore from 'stores/PreferencesStore';
import ComposeStore from 'stores/ComposeStore';

import AvatarItem from 'components/common/AvatarItem.react';
import MentionDropdown from 'components/common/MentionDropdown.react';
import EmojiDropdown from 'components/common/EmojiDropdown.react';

let getStateFromStores = () => {
  return {
    text: ComposeStore.getText(),
    profile: ActorClient.getUser(ActorClient.getUid()),
    sendByEnter: PreferencesStore.istSendByEnterEnabled(),
    mentions: ComposeStore.getMentions()
  };
};

@ReactMixin.decorate(PureRenderMixin)
class ComposeSection extends React.Component {
  static propTypes = {
    peer: React.PropTypes.object.isRequired
  };

  constructor(props) {
    super(props);

    this.state = _.assign({
      isEmojiDropdownShow: false
    }, getStateFromStores());

    GroupStore.addChangeListener(this.onChange);
    ComposeStore.addChangeListener(this.onChange);
    PreferencesStore.addChangeListener(this.onChange);
  }

  componentWillUnmount() {
    GroupStore.removeChangeListener(this.onChange);
    ComposeStore.removeChangeListener(this.onChange);
    PreferencesStore.removeChangeListener(this.onChange);
  }

  onChange = () => {
    this.setState(getStateFromStores());
  };

  onMessageChange = event => {
    const text = event.target.value;
    const { peer } = this.props;

    ComposeActionCreators.onTyping(peer, text, this.getCaretPosition());
  };

  onKeyDown = event => {
    const { mentions, sendByEnter } = this.state;

    if (mentions === null) {
      if (sendByEnter === true) {
        if (event.keyCode === KeyCodes.ENTER && !event.shiftKey) {
          event.preventDefault();
          this.sendTextMessage();
        }
      } else {
        if (event.keyCode === KeyCodes.ENTER && event.metaKey) {
          event.preventDefault();
          this.sendTextMessage();
        }
      }
    }
  };

  sendTextMessage = () => {
    const { text } = this.state;
    const { peer } = this.props;

    if (text.trim().length !== 0) {
      MessageActionCreators.sendTextMessage(peer, text);
    }
    ComposeActionCreators.cleanText();
  };

  onSendFileClick = () => {
    const fileInput = document.getElementById('composeFileInput');
    fileInput.click();
  };

  onSendPhotoClick = () => {
    const photoInput = document.getElementById('composePhotoInput');
    photoInput.accept = 'image/*';
    photoInput.click();
  };

  onFileInputChange = () => {
    const files = document.getElementById('composeFileInput').files;
    MessageActionCreators.sendFileMessage(this.props.peer, files[0]);
  };

  onPhotoInputChange = () => {
    const photos = document.getElementById('composePhotoInput').files;
    MessageActionCreators.sendPhotoMessage(this.props.peer, photos[0]);
  };

  onPaste = event => {
    let preventDefault = false;

    _.forEach(event.clipboardData.items, (item) => {
      if (item.type.indexOf('image') !== -1) {
        preventDefault = true;
        MessageActionCreators.sendClipboardPhotoMessage(this.props.peer, item.getAsFile());
      }
    }, this);

    if (preventDefault) {
      event.preventDefault();
    }
  };

  onMentionSelect = (mention) => {
    const { peer } = this.props;
    const { text } = this.state;

    ComposeActionCreators.insertMention(peer, text, this.getCaretPosition(), mention);
    React.findDOMNode(this.refs.area).focus();
  };

  onMentionClose = () => {
    ComposeActionCreators.closeMention();
  };

  getCaretPosition = () => {
    const composeArea = React.findDOMNode(this.refs.area);
    const selection = Inputs.getInputSelection(composeArea);
    return selection.start;
  };

  onEmojiDropdownSelect = (emoji) => {
    ComposeActionCreators.insertEmoji(this.state.text, this.getCaretPosition(), emoji);
    React.findDOMNode(this.refs.area).focus();
  };
  onEmojiDropdownClose = () => this.setState({isEmojiDropdownShow: false});
  onEmojiShowClick = () => this.setState({isEmojiDropdownShow: true});

  render() {
    const { text, profile, mentions, isEmojiDropdownShow } = this.state;

    const emojiOpenerClassName = classnames('emoji-opener material-icons', {
      'emoji-opener--active': isEmojiDropdownShow
    });

    return (

        <MentionDropdown mentions={mentions}
                         onSelect={this.onMentionSelect}
                         onClose={this.onMentionClose}/>

        <EmojiDropdown isOpen={isEmojiDropdownShow}
                       onSelect={this.onEmojiDropdownSelect}
                       onClose={this.onEmojiDropdownClose}/>
        insert_emoticon

        <AvatarItem className="my-avatar"
                    image={profile.avatar}
                    placeholder={profile.placeholder}
                    title={profile.name}/>

        <textarea className="compose__message"
                  onChange={this.onMessageChange}
                  onKeyDown={this.onKeyDown}
                  value={text}
                  ref="area"/>

          <button className="button attachment" onClick={this.onSendFileClick}>
            attachment Send file
          </button>
          <button className="button attachment" onClick={this.onSendPhotoClick}>
            photo_camera Send photo
          </button>

          <button className="button button--lightblue" onClick={this.sendTextMessage}>Send</button>

          <input id="composeFileInput"
                 onChange={this.onFileInputChange}
                 type="file"/>
          <input id="composePhotoInput"
                 onChange={this.onPhotoInputChange}
                 type="file"/>

    );
  }
}

export default ComposeSection;
<commit_msg>fix(web): fix sending same file<commit_after>/*
 * Copyright (C) 2015 Actor LLC. <https://actor.im>
 */

import _ from 'lodash';

import React from 'react';
import classnames from 'classnames';
import ReactMixin from 'react-mixin';
import addons from 'react/addons';
const {addons: { PureRenderMixin }} = addons;

import ActorClient from 'utils/ActorClient';
import Inputs from 'utils/Inputs';

import { KeyCodes } from 'constants/ActorAppConstants';

import MessageActionCreators from 'actions/MessageActionCreators';
import ComposeActionCreators from 'actions/ComposeActionCreators';

import GroupStore from 'stores/GroupStore';
import PreferencesStore from 'stores/PreferencesStore';
import ComposeStore from 'stores/ComposeStore';

import AvatarItem from 'components/common/AvatarItem.react';
import MentionDropdown from 'components/common/MentionDropdown.react';
import EmojiDropdown from 'components/common/EmojiDropdown.react';

let getStateFromStores = () => {
  return {
    text: ComposeStore.getText(),
    profile: ActorClient.getUser(ActorClient.getUid()),
    sendByEnter: PreferencesStore.istSendByEnterEnabled(),
    mentions: ComposeStore.getMentions()
  };
};

@ReactMixin.decorate(PureRenderMixin)
class ComposeSection extends React.Component {
  static propTypes = {
    peer: React.PropTypes.object.isRequired
  };

  constructor(props) {
    super(props);

    this.state = _.assign({
      isEmojiDropdownShow: false
    }, getStateFromStores());

    GroupStore.addChangeListener(this.onChange);
    ComposeStore.addChangeListener(this.onChange);
    PreferencesStore.addChangeListener(this.onChange);
  }

  componentWillUnmount() {
    GroupStore.removeChangeListener(this.onChange);
    ComposeStore.removeChangeListener(this.onChange);
    PreferencesStore.removeChangeListener(this.onChange);
  }

  onChange = () => {
    this.setState(getStateFromStores());
  };

  onMessageChange = event => {
    const text = event.target.value;
    const { peer } = this.props;

    ComposeActionCreators.onTyping(peer, text, this.getCaretPosition());
  };

  onKeyDown = event => {
    const { mentions, sendByEnter } = this.state;

    if (mentions === null) {
      if (sendByEnter === true) {
        if (event.keyCode === KeyCodes.ENTER && !event.shiftKey) {
          event.preventDefault();
          this.sendTextMessage();
        }
      } else {
        if (event.keyCode === KeyCodes.ENTER && event.metaKey) {
          event.preventDefault();
          this.sendTextMessage();
        }
      }
    }
  };

  sendTextMessage = () => {
    const { text } = this.state;
    const { peer } = this.props;

    if (text.trim().length !== 0) {
      MessageActionCreators.sendTextMessage(peer, text);
    }
    ComposeActionCreators.cleanText();
  };

  onSendFileClick = () => {
    const fileInput = React.findDOMNode(this.refs.composeFileInput);
    fileInput.click();
  };

  onSendPhotoClick = () => {
    const photoInput = React.findDOMNode(this.refs.composePhotoInput);
    photoInput.accept = 'image/*';
    photoInput.click();
  };

  onFileInputChange = () => {
    const fileInput = React.findDOMNode(this.refs.composeFileInput);
    MessageActionCreators.sendFileMessage(this.props.peer, fileInput.files[0]);
    this.resetSendFileForm();
  };

  onPhotoInputChange = () => {
    console.debug('onPhotoInputChange');
    const photoInput = React.findDOMNode(this.refs.composePhotoInput);
    MessageActionCreators.sendPhotoMessage(this.props.peer, photoInput.files[0]);
    this.resetSendFileForm();
  };

  resetSendFileForm = () => {
    const form = React.findDOMNode(this.refs.sendFileForm);
    form.reset();
  };

  onPaste = event => {
    let preventDefault = false;

    _.forEach(event.clipboardData.items, (item) => {
      if (item.type.indexOf('image') !== -1) {
        preventDefault = true;
        MessageActionCreators.sendClipboardPhotoMessage(this.props.peer, item.getAsFile());
      }
    }, this);

    if (preventDefault) {
      event.preventDefault();
    }
  };

  onMentionSelect = (mention) => {
    const { peer } = this.props;
    const { text } = this.state;

    ComposeActionCreators.insertMention(peer, text, this.getCaretPosition(), mention);
    React.findDOMNode(this.refs.area).focus();
  };

  onMentionClose = () => {
    ComposeActionCreators.closeMention();
  };

  getCaretPosition = () => {
    const composeArea = React.findDOMNode(this.refs.area);
    const selection = Inputs.getInputSelection(composeArea);
    return selection.start;
  };

  onEmojiDropdownSelect = (emoji) => {
    ComposeActionCreators.insertEmoji(this.state.text, this.getCaretPosition(), emoji);
    React.findDOMNode(this.refs.area).focus();
  };
  onEmojiDropdownClose = () => this.setState({isEmojiDropdownShow: false});
  onEmojiShowClick = () => this.setState({isEmojiDropdownShow: true});

  render() {
    const { text, profile, mentions, isEmojiDropdownShow } = this.state;

    const emojiOpenerClassName = classnames('emoji-opener material-icons', {
      'emoji-opener--active': isEmojiDropdownShow
    });

    return (

        <MentionDropdown mentions={mentions}
                         onSelect={this.onMentionSelect}
                         onClose={this.onMentionClose}/>

        <EmojiDropdown isOpen={isEmojiDropdownShow}
                       onSelect={this.onEmojiDropdownSelect}
                       onClose={this.onEmojiDropdownClose}/>
        insert_emoticon

        <AvatarItem className="my-avatar"
                    image={profile.avatar}
                    placeholder={profile.placeholder}
                    title={profile.name}/>

        <textarea className="compose__message"
                  onChange={this.onMessageChange}
                  onKeyDown={this.onKeyDown}
                  value={text}
                  ref="area"/>

          <button className="button attachment" onClick={this.onSendFileClick}>
            attachment Send file
          </button>
          <button className="button attachment" onClick={this.onSendPhotoClick}>
            photo_camera Send photo
          </button>

          <button className="button button--lightblue" onClick={this.sendTextMessage}>Send</button>

        <form className="compose__hidden" ref="sendFileForm">
          <input ref="composeFileInput" onChange={this.onFileInputChange} type="file"/>
          <input ref="composePhotoInput" onChange={this.onPhotoInputChange} type="file"/>
        </form>

    );
  }
}

export default ComposeSection;
<|endoftext|>


<commit_before>import is from 'is_js';

const COLOR_SPECS = [{
  nameRegexp: /^[A-D]/i,
  bgFill: '#59295A',
  textFill: 'white',
}, {
  nameRegexp: /^[E-H]/i,
  bgFill: '#92205F',
  textFill: 'white',
}, {
  nameRegexp: /^[I-L]/i,
  bgFill: '#D8213A',
  textFill: 'white',
}, {
  nameRegexp: /^[M-P]/i,
  bgFill: '#E9852C',
  textFill: 'white',
}, {
  nameRegexp: /^[Q-T]/i,
  bgFill: '#FBCB22',
  textFill: 'black',
}, {
  nameRegexp: /^[U-X]/i,
  bgFill: '#00773F',
  textFill: 'white',
}, {
  nameRegexp: /^[Y-Z]/i,
  bgFill: '#1C8FC2',
  textFill: 'white',
}];

// https://github.com/bhovhannes/svg-url-loader/blob/4bfa8519/index.js
/* eslint-disable */
const convertSvgToDataUri = (html) => {
  let data = html
    .replace(/\n/g, '')
    .replace(/"/g, "'")
    .replace(/\s+/g, " ")
    .replace(/[{}\|\\\^~\[\]`"<>#%]/g, (match) =>
      '%' + match[0].charCodeAt(0).toString(16).toUpperCase());
  data = 'data:image/svg+xml;charset=utf8,' + data.trim();
  return data;
};
/* eslint-enable */

export const generatePlaceholderSvgXml = (userFirstName, userLastName,
    forcedBgFill, forcedTextFill) => {
  const userFirstNameOrEmpty =
      is.string(userFirstName) && is.not.empty(userFirstName) ? userFirstName : '?';
  const userLastNameOrEmpty =
      is.string(userLastName) && is.not.empty(userLastName) ? userLastName : '?';
  const userFirstInitial = userFirstNameOrEmpty.charAt(0).toUpperCase();
  const userLastInitial = userLastNameOrEmpty.charAt(0).toUpperCase();
  const colorSpec = COLOR_SPECS.find((m) => m.nameRegexp.test(userFirstNameOrEmpty)) || {};
  // `dy` ref: http://stackoverflow.com/a/31376501
  return `<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <rect width="100%" height="100%" fill="${forcedBgFill || colorSpec.bgFill || '#FFF'}" />
    <text fill="${forcedTextFill || colorSpec.textFill || '#000'}"
        font-size="14px"
        font-weight="bold"
        font-family="Helvetica"
        text-anchor="middle"
        x="50%" y="50%" dy=".35em">
      ${userFirstInitial || '?'}${userLastInitial || '?'}
    </text>
  </svg>`;
};

export const generatePlaceholderSvgDataUri = (userFirstName, userLastName,
    forcedBgFill, forcedTextFill) =>
  convertSvgToDataUri(
    generatePlaceholderSvgXml(userFirstName, userLastName,
        forcedBgFill, forcedTextFill));

export default generatePlaceholderSvgDataUri;
<commit_msg>Avatar: Using the notification bubble red in placeholder too<commit_after>import is from 'is_js';

const COLOR_SPECS = [{
  nameRegexp: /^[A-D]/i,
  bgFill: '#59295A',  // purple
  textFill: 'white',
}, {
  nameRegexp: /^[E-H]/i,
  bgFill: '#92205F', // magenta
  textFill: 'white',
}, {
  nameRegexp: /^[I-L]/i,
  bgFill: '#DE4C4C',  // red
  textFill: 'white',
}, {
  nameRegexp: /^[M-P]/i,
  bgFill: '#E9852C',  // dark orange
  textFill: 'white',
}, {
  nameRegexp: /^[Q-T]/i,
  bgFill: '#FBCB22',  // orange
  textFill: 'black',
}, {
  nameRegexp: /^[U-X]/i,
  bgFill: '#00773F',  // green
  textFill: 'white',
}, {
  nameRegexp: /^[Y-Z]/i,
  bgFill: '#1C8FC2',  // cyan
  textFill: 'white',
}];

// https://github.com/bhovhannes/svg-url-loader/blob/4bfa8519/index.js
/* eslint-disable */
const convertSvgToDataUri = (html) => {
  let data = html
    .replace(/\n/g, '')
    .replace(/"/g, "'")
    .replace(/\s+/g, " ")
    .replace(/[{}\|\\\^~\[\]`"<>#%]/g, (match) =>
      '%' + match[0].charCodeAt(0).toString(16).toUpperCase());
  data = 'data:image/svg+xml;charset=utf8,' + data.trim();
  return data;
};
/* eslint-enable */

export const generatePlaceholderSvgXml = (userFirstName, userLastName,
    forcedBgFill, forcedTextFill) => {
  const userFirstNameOrEmpty =
      is.string(userFirstName) && is.not.empty(userFirstName) ? userFirstName : '?';
  const userLastNameOrEmpty =
      is.string(userLastName) && is.not.empty(userLastName) ? userLastName : '?';
  const userFirstInitial = userFirstNameOrEmpty.charAt(0).toUpperCase();
  const userLastInitial = userLastNameOrEmpty.charAt(0).toUpperCase();
  const colorSpec = COLOR_SPECS.find((m) => m.nameRegexp.test(userFirstNameOrEmpty)) || {};
  // `dy` ref: http://stackoverflow.com/a/31376501
  return `<svg height="100%" width="100%" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <rect width="100%" height="100%" fill="${forcedBgFill || colorSpec.bgFill || '#FFF'}" />
    <text fill="${forcedTextFill || colorSpec.textFill || '#000'}"
        font-size="14px"
        font-weight="bold"
        font-family="Helvetica"
        text-anchor="middle"
        x="50%" y="50%" dy=".35em">
      ${userFirstInitial || '?'}${userLastInitial || '?'}
    </text>
  </svg>`;
};

export const generatePlaceholderSvgDataUri = (userFirstName, userLastName,
    forcedBgFill, forcedTextFill) =>
  convertSvgToDataUri(
    generatePlaceholderSvgXml(userFirstName, userLastName,
        forcedBgFill, forcedTextFill));

export default generatePlaceholderSvgDataUri;
<|endoftext|>


<commit_before>!function(e){function t(r){if(n[r])return n[r].exports;var i=n[r]={exports:{},id:r,loaded:!1};return e[r].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){n(1),e.exports=n(2)},function(e,t){var n=(window.$||void 0,window.document),r={checkIsEmtpy:function(e,t){try{if(mesage=t||" Invalid Value ","object"==typeof e){if(!e||0==Object.keys(e).length)throw t;if(!e)throw t;if(!e.length)throw t}}catch(e){console.error(" Error on emptyChecker : checkIsEmtpy() ",e)}}};window.emptyChecker=r,function(e){var t={init:function(){this.currentDate=""},getCurrentDate:function(){return this.currentDate},setCurrentDate:function(e){this.currentDate=e}},r={init:function(){t.init(),i.init(),this.initialize()},initialize:function(){this.setUpCurrentDate(),this.greetUser()},setUpCurrentDate:function(){try{t.setCurrentDate(new Date)}catch(e){console.error(" Erro on setting up current Date ",e)}},greetUser:function(e){var n=t.getCurrentDate(),r=n.getHours(),o=this.getGreetings(r),c=i.render();c.renderGreetingMessage(o)},getGreetings:function(e){try{if(window.emptyChecker.checkIsEmtpy(e," Invalid Hours Passed / Hours can not be Emtpy "),e<12)return"Nothing Big in here! To further lookup"}catch(e){console.error(" exception araised on get greetings  ",e)}}},i={init:function(){this.greetUser=n.getElementById("greet-user")},render:function(){var e=this;return{renderGreetingMessage:function(t){e.greetUser.innerHTML=t||" Nothing Big in here! To further lookup..!"}}}};e.onLoadProcessor={GreetUser:r.init.bind(r)}}(window),window.addEventListener("load",window.onLoadProcessor.GreetUser)},function(e,t){window.AudioContext=window.AudioContext||window.webkitAudioContext;var n,r=new AudioContext,i=!1,o=r.createGain(),c=function(e){var t=20,n=2e3;return e/window.innerWidth*n+t},u=function(e){var t=0,n=1;return 1-e/window.innerHeight*n+t};window.document.body.addEventListener("mousedown",function(e){i=!0,n=r.createOscillator(),n.frequency.setTargetAtTime(c(e.clientX),r.currentTime,.01),n.connect(o),o.connect(r.destination),n.start(r.currentTime)}),window.document.body.addEventListener("mouseup",function(){i=!1,n.stop(r.currentTime),n.disconnect()}),window.document.body.addEventListener("mousemove",function(e){i&&o.gain.setTargetAtTime(u(e.clientY),r.currentTime,.01)})}]);<commit_msg>latest bundles<commit_after>var $=window.$||void 0,document=window.document,emptyChecker={checkIsEmtpy:function(e,t){try{if(mesage=t||" Invalid Value ","object"==typeof e){if(!e||0==Object.keys(e).length)throw t;if(!e)throw t;if(!e.length)throw t}}catch(e){console.error(" Error on emptyChecker : checkIsEmtpy() ",e)}}};window.emptyChecker=emptyChecker,function(e){var n={init:function(){this.currentDate=""},getCurrentDate:function(){return this.currentDate},setCurrentDate:function(e){this.currentDate=e}},t={init:function(){n.init(),i.init(),this.initialize()},initialize:function(){this.setUpCurrentDate(),this.greetUser()},setUpCurrentDate:function(){try{n.setCurrentDate(new Date)}catch(e){console.error(" Erro on setting up current Date ",e)}},greetUser:function(e){var t=n.getCurrentDate().getHours(),r=this.getGreetings(t);i.render().renderGreetingMessage(r)},getGreetings:function(e){try{if(window.emptyChecker.checkIsEmtpy(e," Invalid Hours Passed / Hours can not be Emtpy "),e<12)return"Greetings, You are on boarded !"}catch(e){console.error(" exception araised on get greetings  ",e)}}},i={init:function(){this.greetUser=document.getElementById("greet-user")},render:function(){var t=this;return{renderGreetingMessage:function(e){t.greetUser.innerHTML=e||"Greetings, You are on boarded !"}}}};e.onLoadProcessor={GreetUser:t.init.bind(t)}}(window),window.addEventListener("load",window.onLoadProcessor.GreetUser);<|endoftext|>


<commit_before>/* global tus */
/* eslint no-console: 0 */

var upload = null;
var stopBtn = document.querySelector("#stop-btn");
var resumeCheckbox = document.querySelector("#resume");
var input = document.querySelector("input[type=file]");
var progress = document.querySelector(".progress");
var progressBar = progress.querySelector(".bar");
var alertBox = document.querySelector("#support-alert");
var chunkInput = document.querySelector("#chunksize");
var endpointInput = document.querySelector("#endpoint");

if (!tus.isSupported) {
  alertBox.className = alertBox.className.replace("hidden", "");
}

stopBtn.addEventListener("click", function (e) {
  e.preventDefault();

  if (upload) {
    upload.abort();
  }
});

input.addEventListener("change", function (e) {
  var file = e.target.files[0];
  // Only continue if a file has actually been selected.
  // IE will trigger a change event if we reset the input element
  // inside reset() and we do not want to blow up later.
  if (!file) {
      return;
  }

  console.log("selected file", file);

  stopBtn.classList.remove("disabled");
  var endpoint = endpointInput.value;
  var chunkSize = parseInt(chunkInput.value, 10);
  if (isNaN(chunkSize)) {
    chunkSize = Infinity;
  }

  var options = {
    endpoint: endpoint,
    resume: !resumeCheckbox.checked,
    chunkSize: chunkSize,
    metadata: {
        filename: file.name
    },
    onError: function (error) {
      if (error.originalRequest) {
        if (confirm("Failed because: " + error + "\nDo you want to retry?")) {
          options.resume = false;
          options.uploadUrl = upload.url;
          upload = new tus.Upload(file, options);
          upload.start();
          return;
        }
      } else {
        alert("Failed because: " + error);
      }

      reset();
    },
    onProgress: function (bytesUploaded, bytesTotal) {
      var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
      progressBar.style.width = percentage + "%";
      console.log(bytesUploaded, bytesTotal, percentage + "%");
    },
    onSuccess: function () {
      reset();
      var anchor = document.createElement("a");
      anchor.textContent = "Download " + upload.file.name + " (" + upload.file.size + " bytes)";
      anchor.href = upload.url;
      anchor.className = "btn btn-success";
      e.target.parentNode.appendChild(anchor);
    }
  };

  upload = new tus.Upload(file, options);
  upload.start();
});

function reset() {
  input.value = "";
  stopBtn.classList.add("disabled");
  progress.classList.remove("active");
}
<commit_msg>Enable retries in demo<commit_after>/* global tus */
/* eslint no-console: 0 */

var upload = null;
var stopBtn = document.querySelector("#stop-btn");
var resumeCheckbox = document.querySelector("#resume");
var input = document.querySelector("input[type=file]");
var progress = document.querySelector(".progress");
var progressBar = progress.querySelector(".bar");
var alertBox = document.querySelector("#support-alert");
var chunkInput = document.querySelector("#chunksize");
var endpointInput = document.querySelector("#endpoint");

if (!tus.isSupported) {
  alertBox.className = alertBox.className.replace("hidden", "");
}

stopBtn.addEventListener("click", function (e) {
  e.preventDefault();

  if (upload) {
    upload.abort();
  }
});

input.addEventListener("change", function (e) {
  var file = e.target.files[0];
  // Only continue if a file has actually been selected.
  // IE will trigger a change event if we reset the input element
  // inside reset() and we do not want to blow up later.
  if (!file) {
      return;
  }

  console.log("selected file", file);

  stopBtn.classList.remove("disabled");
  var endpoint = endpointInput.value;
  var chunkSize = parseInt(chunkInput.value, 10);
  if (isNaN(chunkSize)) {
    chunkSize = Infinity;
  }

  var options = {
    endpoint: endpoint,
    resume: !resumeCheckbox.checked,
    chunkSize: chunkSize,
    retryDelays: [0, 1000, 2000],
    metadata: {
        filename: file.name
    },
    onError: function (error) {
      if (error.originalRequest) {
        if (confirm("Failed because: " + error + "\nDo you want to retry?")) {
          options.resume = false;
          options.uploadUrl = upload.url;
          upload = new tus.Upload(file, options);
          upload.start();
          return;
        }
      } else {
        alert("Failed because: " + error);
      }

      reset();
    },
    onProgress: function (bytesUploaded, bytesTotal) {
      var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2);
      progressBar.style.width = percentage + "%";
      console.log(bytesUploaded, bytesTotal, percentage + "%");
    },
    onSuccess: function () {
      reset();
      var anchor = document.createElement("a");
      anchor.textContent = "Download " + upload.file.name + " (" + upload.file.size + " bytes)";
      anchor.href = upload.url;
      anchor.className = "btn btn-success";
      e.target.parentNode.appendChild(anchor);
    }
  };

  upload = new tus.Upload(file, options);
  upload.start();
});

function reset() {
  input.value = "";
  stopBtn.classList.add("disabled");
  progress.classList.remove("active");
}
<|endoftext|>


<commit_before>exports = module.exports = function(IoC, negotiator, interpreter, translator, unsealer, sealer, logger) {
  var Tokens = require('tokens').Tokens;

  var tokens = new Tokens();

  return Promise.resolve(tokens)
    .then(function(tokens) {
      var components = IoC.components('http://i.bixbyjs.org/tokens/Token');
      return Promise.all(components.map(function(comp) { return comp.create(); } ))
        .then(function(formats) {
          formats.forEach(function(format, i) {
            var type = components[i].a['@type'];
            logger.info('Loaded token type: ' + type);
            tokens.format(type, format)
          });
        })
        .then(function() {
          return tokens;
        });
    })
    .then(function(tokens) {
      var api = {};

      api.seal = function(claims, recipients, options, cb) {
        console.log('SEAL THIS MESSAGE!');
        console.log(claims)

        var sealer;
        try {
          sealer = tokens.createSealer('application/jwt');
        } catch (ex) {
          return cb(ex);
        }

        sealer.seal(claims, recipients, options, function(err, token) {
          console.log('SEALED IT!');
          console.log(err)
          console.log(token)

          if (err) { return cb(err); }
          return cb(null, token);
        });
      };

      api.unseal = function(token, cb) {
        console.log('UNSEAL THIS')
        console.log(token)

        var unsealer;
        try {
          unsealer = tokens.createUnsealer();
        } catch (ex) {
          return cb(ex);
        }

        unsealer.unseal(token, function(err, msg, extra) {
          if (err) { return cb(err); }

          console.log('MESSAG!');
          console.log(msg);
          console.log(extra);

          return cb(null, msg.claims);
        });
      };

      api.negotiate = function(formats) {
        return negotiator.negotiate(formats);
      }

      api.cipher = function(ctx, options, cb) {
        if (typeof options == 'function') {
          cb = options;
          options = undefined;
        }
        options = options || {};

        translator.translate(ctx, options, function(err, claims) {
          if (err) { return cb(err); }

          // Marshal context necessary for sealing the token.  This includes this
          // that are conceptually "header" information, such as the audience, time
          // of issuance, expiration, etc.
          options.audience = ctx.audience;

          sealer.seal(claims, options, function(err, token) {
            if (err) { return cb(err); }
            return cb(null, token);
          });
        });
      }

      api.decipher = function(token, options, cb) {
        if (typeof options == 'function') {
          cb = options;
          options = undefined;
        }
        options = options || {};

        unsealer.unseal(token, options, function(err, tok) {
          if (err) { return cb(err); }

          interpreter.interpret(tok, options, function(err, sctx) {
            if (err) { return cb(err); }
            return cb(null, sctx, tok);
          });
        });
      }

      return api;
    });
};

exports['@implements'] = 'http://i.bixbyjs.org/tokens';
exports['@singleton'] = true;
exports['@require'] = [
  '!container',
  'http://i.bixbyjs.org/tokens/Negotiator',
  './interpreter',
  './translator',
  './unsealer',
  './sealer',
  'http://i.bixbyjs.org/Logger'
];
<commit_msg>Respect type option to seal.<commit_after>exports = module.exports = function(IoC, negotiator, interpreter, translator, unsealer, sealer, logger) {
  var Tokens = require('tokens').Tokens;

  var tokens = new Tokens();

  return Promise.resolve(tokens)
    .then(function(tokens) {
      var components = IoC.components('http://i.bixbyjs.org/tokens/Token');
      return Promise.all(components.map(function(comp) { return comp.create(); } ))
        .then(function(formats) {
          formats.forEach(function(format, i) {
            var type = components[i].a['@type'];
            logger.info('Loaded token type: ' + type);
            tokens.format(type, format)
          });
        })
        .then(function() {
          return tokens;
        });
    })
    .then(function(tokens) {
      var api = {};

      api.seal = function(claims, recipients, options, cb) {
        console.log('SEAL THIS MESSAGE!');
        console.log(claims)

        var type = options.type || 'application/jwt';

        var sealer;
        try {
          sealer = tokens.createSealer(type);
        } catch (ex) {
          return cb(ex);
        }

        sealer.seal(claims, recipients, options, function(err, token) {
          console.log('SEALED IT!');
          console.log(err)
          console.log(token)

          if (err) { return cb(err); }
          return cb(null, token);
        });
      };

      api.unseal = function(token, cb) {
        console.log('UNSEAL THIS')
        console.log(token)

        var unsealer;
        try {
          unsealer = tokens.createUnsealer();
        } catch (ex) {
          return cb(ex);
        }

        unsealer.unseal(token, function(err, msg, extra) {
          if (err) { return cb(err); }

          console.log('MESSAG!');
          console.log(msg);
          console.log(extra);

          return cb(null, msg.claims);
        });
      };

      api.negotiate = function(formats) {
        return negotiator.negotiate(formats);
      }

      api.cipher = function(ctx, options, cb) {
        if (typeof options == 'function') {
          cb = options;
          options = undefined;
        }
        options = options || {};

        translator.translate(ctx, options, function(err, claims) {
          if (err) { return cb(err); }

          // Marshal context necessary for sealing the token.  This includes this
          // that are conceptually "header" information, such as the audience, time
          // of issuance, expiration, etc.
          options.audience = ctx.audience;

          sealer.seal(claims, options, function(err, token) {
            if (err) { return cb(err); }
            return cb(null, token);
          });
        });
      }

      api.decipher = function(token, options, cb) {
        if (typeof options == 'function') {
          cb = options;
          options = undefined;
        }
        options = options || {};

        unsealer.unseal(token, options, function(err, tok) {
          if (err) { return cb(err); }

          interpreter.interpret(tok, options, function(err, sctx) {
            if (err) { return cb(err); }
            return cb(null, sctx, tok);
          });
        });
      }

      return api;
    });
};

exports['@implements'] = 'http://i.bixbyjs.org/tokens';
exports['@singleton'] = true;
exports['@require'] = [
  '!container',
  'http://i.bixbyjs.org/tokens/Negotiator',
  './interpreter',
  './translator',
  './unsealer',
  './sealer',
  'http://i.bixbyjs.org/Logger'
];
<|endoftext|>


<commit_before>function Sprite(size, position, animationSpeed, frames) {
  this.size = size; // in "pixels" per tile
  this.position = position; // 2d Vector
  this.currentFrame = 0;
  this.tick = 0;
  this.frames = frames || [];
  this.cache = {};
  this.animationDelta = 0;
  this.animationSpeed = animationSpeed || 100;
}

// globally shared sprite cache
Sprite.cache = {};

Sprite.prototype.update = function() {
  if(this.animationDelta > this.animationSpeed){
    this.currentFrame = this.tick % this.frames.length;
    this.tick++;
    this.animationDelta = 0;
  }else{
     this.animationDelta += delta;
  }

  this.pixelSize = Math.floor(TILESIZE / this.size);
};

Sprite.prototype.draw = function() {
  var start = this.position.mul(TILESIZE); // pixel location on canvas
  var end = start.add(TILESIZE); // this is the opposite corner of the tile
  context.moveTo(start.x, start.y);
  // debugger;
  // TODO: refactor this one
  for(var x = start.x, tx = 0; x < end.x; x += this.pixelSize, tx++){
    for(var y = start.y, ty = 0; y < end.y; y += this.pixelSize, ty++){
      try{
        context.fillStyle = this.frames[this.currentFrame][tx][ty];
        context.fillRect(x, y, this.pixelSize, this.pixelSize);
      }catch(e){
        // FIXME: sometimes drawX or drawY exceeds the frame dimensions, why?
      }
    }
  }
};

// TODO: fix this function, the idea here is to cache this sprite by drawing
// it to a hidden canvas, so that when we do the drawing on the visible
// canvas we can do a drawImage using the image that we have predrawn.
// this is theoretically much faster
Sprite.prototype.cacheFrames = function() {
  // cCanvas is a sprite sheet containing the drawn frames
  var cCanvas = document.createElement('canvas');
  cCanvas.height = TILESIZE;
  cCanvas.width = TILESIZE * this.frames.length;
  var cContext = cCanvas.getContext('2d');
  var pixelSize = Math.floor(TILESIZE / this.size);

  for(var frame = 0; frame < this.frames.length; frame++){
    cContext.moveTo(frame * TILESIZE, 0);

    // draw frame to section of sprite sheet canvas
    for(var x = 0, tx = 0; x < TILESIZE; x += pixelSize, tx++){
      for(var y = 0, ty = 0; y < TILESIZE; y += pixelSize, ty++){
        try{
          cContext.fillStyle = this.frames[frame][tx][ty];
          cContext.fillRect(x, y, pixelSize, pixelSize);
        }catch(e){
          // FIXME: sometimes drawX or drawY exceeds the frame dimensions, why?
        }
      }
    }

    // use frame contents as cache-key
    cacheKey = this.frames[frame].join('');
    Sprite.cache[cacheKey] = cCanvas;
  }
  return Sprite.cache;
};

<commit_msg>change order of args<commit_after>function Sprite(size, position, frames, animationSpeed) {
  this.size = size; // in "pixels" per tile
  this.position = position; // 2d Vector
  this.currentFrame = 0;
  this.tick = 0;
  this.frames = frames || [];
  this.cache = {};
  this.animationDelta = 0;
  this.animationSpeed = animationSpeed || 100;
}

// globally shared sprite cache
Sprite.cache = {};

Sprite.prototype.update = function() {
  if(this.animationDelta > this.animationSpeed){
    this.currentFrame = this.tick % this.frames.length;
    this.tick++;
    this.animationDelta = 0;
  }else{
     this.animationDelta += delta;
  }

  this.pixelSize = Math.floor(TILESIZE / this.size);
};

Sprite.prototype.draw = function() {
  var start = this.position.mul(TILESIZE); // pixel location on canvas
  var end = start.add(TILESIZE); // this is the opposite corner of the tile
  context.moveTo(start.x, start.y);
  // debugger;
  // TODO: refactor this one
  for(var x = start.x, tx = 0; x < end.x; x += this.pixelSize, tx++){
    for(var y = start.y, ty = 0; y < end.y; y += this.pixelSize, ty++){
      try{
        context.fillStyle = this.frames[this.currentFrame][tx][ty];
        context.fillRect(x, y, this.pixelSize, this.pixelSize);
      }catch(e){
        // FIXME: sometimes drawX or drawY exceeds the frame dimensions, why?
      }
    }
  }
};

// TODO: fix this function, the idea here is to cache this sprite by drawing
// it to a hidden canvas, so that when we do the drawing on the visible
// canvas we can do a drawImage using the image that we have predrawn.
// this is theoretically much faster
Sprite.prototype.cacheFrames = function() {
  // cCanvas is a sprite sheet containing the drawn frames
  var cCanvas = document.createElement('canvas');
  cCanvas.height = TILESIZE;
  cCanvas.width = TILESIZE * this.frames.length;
  var cContext = cCanvas.getContext('2d');
  var pixelSize = Math.floor(TILESIZE / this.size);

  for(var frame = 0; frame < this.frames.length; frame++){
    cContext.moveTo(frame * TILESIZE, 0);

    // draw frame to section of sprite sheet canvas
    for(var x = 0, tx = 0; x < TILESIZE; x += pixelSize, tx++){
      for(var y = 0, ty = 0; y < TILESIZE; y += pixelSize, ty++){
        try{
          cContext.fillStyle = this.frames[frame][tx][ty];
          cContext.fillRect(x, y, pixelSize, pixelSize);
        }catch(e){
          // FIXME: sometimes drawX or drawY exceeds the frame dimensions, why?
        }
      }
    }

    // use frame contents as cache-key
    cacheKey = this.frames[frame].join('');
    Sprite.cache[cacheKey] = cCanvas;
  }
  return Sprite.cache;
};

<|endoftext|>


<commit_before>/* eslint-env node */
const electron = require("electron")
const {app, BrowserWindow, ipcMain, Menu, shell} = electron
const isDev = require("electron-is-dev")
const { URL } = require("url")
const defaultMenu = require("electron-default-menu")
const updater = require("./updater")
const logger = require("./logger")
const path = require("path")

const {authorizeUser, setAccessToken} = require("./userAuthentication")

let mainWindow
let loadOnReady = null

const DEFAULT_PROTOCOL_HANDLER = "x-github-classroom"

if (require("electron-squirrel-startup")) app.quit()

logger.init()

const createWindow = () => {
  logger.info("creating app window")

  const menu = defaultMenu(app, shell)
  Menu.setApplicationMenu(Menu.buildFromTemplate(menu))

  mainWindow = new BrowserWindow({width: 1200, height: 750, titleBarStyle: "hidden", show: false})
  const url = `file://${__dirname}/index.html`
  mainWindow.loadURL(url)

  if (isDev) {
    mainWindow.webContents.openDevTools()
  }

  if (!isDev) {
    const msBetweenUpdates = 1000 * 60 * 30
    updater.start(app, msBetweenUpdates)
  }

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

  ipcMain.on("initialized", async () => {
    if (loadOnReady != null) {
      // If open-url event was fired before app was ready
      await setAccessToken(loadOnReady.code, mainWindow)
      loadPopulatePage(loadOnReady.assignmentURL)
      loadOnReady = null
    }

    mainWindow.show()
  })

  ipcMain.on("requestAuthorization", () => {
    authorizeUser(mainWindow, DEFAULT_PROTOCOL_HANDLER)
  })
}

const loadPopulatePage = (assignmentURL) => {
  mainWindow.webContents.send("open-url", assignmentURL)
}

const setInstanceProtocolHandler = () => {
  app.setAsDefaultProtocolClient(DEFAULT_PROTOCOL_HANDLER)

  return app.makeSingleInstance((argv) => {
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()

      if (process.platform === "win32") {
        const url = argv.find(function (arg) {
          return /^x-github-classroom:\/\//.test(arg)
        })
        if (url) app.emit("open-url", null, url)
      }
    }
  })
}

app.on("open-url", async function (event, urlToOpen) {
  if (event) {
    event.preventDefault()
  }

  let assignmentURL = ""
  const urlParams = new URL(urlToOpen).searchParams
  const isClassroomDeeplink = urlParams.has("assignment_url")
  const isOAuthDeeplink = urlParams.has("code")

  if (isOAuthDeeplink) {
    const oauthCode = urlParams.get("code")

    if (isClassroomDeeplink) {
      assignmentURL = urlParams.get("assignment_url")
    }
    if (app.isReady()) {
      // TODO: Handle rejected promise
      await setAccessToken(oauthCode, mainWindow)
      loadPopulatePage(assignmentURL)
    } else {
      loadOnReady = {
        assignmentURL: assignmentURL,
        code: oauthCode
      }
    }
  }
})

app.on("ready", async () => {
  const anotherInstanceRunning = setInstanceProtocolHandler()
  if (anotherInstanceRunning) app.quit()

  createWindow()
})

app.on("window-all-closed", function () {
  if (process.platform !== "darwin") {
    app.quit()
  }
})

app.on("activate", function () {
  if (mainWindow === null) {
    createWindow()
  }
})
<commit_msg>remove path and exit to fix bug with windows squirell launch<commit_after>/* eslint-env node */
const electron = require("electron")
const {app, BrowserWindow, ipcMain, Menu, shell} = electron
const isDev = require("electron-is-dev")
const { URL } = require("url")
const defaultMenu = require("electron-default-menu")
const updater = require("./updater")
const logger = require("./logger")

const {authorizeUser, setAccessToken} = require("./userAuthentication")

let mainWindow
let loadOnReady = null

const DEFAULT_PROTOCOL_HANDLER = "x-github-classroom"

if (require("electron-squirrel-startup")) app.exit()

logger.init()

const createWindow = () => {
  logger.info("creating app window")

  const menu = defaultMenu(app, shell)
  Menu.setApplicationMenu(Menu.buildFromTemplate(menu))

  mainWindow = new BrowserWindow({width: 1200, height: 750, titleBarStyle: "hidden", show: false})
  const url = `file://${__dirname}/index.html`
  mainWindow.loadURL(url)

  if (isDev) {
    mainWindow.webContents.openDevTools()
  }

  if (!isDev) {
    const msBetweenUpdates = 1000 * 60 * 30
    updater.start(app, msBetweenUpdates)
  }

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

  ipcMain.on("initialized", async () => {
    if (loadOnReady != null) {
      // If open-url event was fired before app was ready
      await setAccessToken(loadOnReady.code, mainWindow)
      loadPopulatePage(loadOnReady.assignmentURL)
      loadOnReady = null
    }

    mainWindow.show()
  })

  ipcMain.on("requestAuthorization", () => {
    authorizeUser(mainWindow, DEFAULT_PROTOCOL_HANDLER)
  })
}

const loadPopulatePage = (assignmentURL) => {
  mainWindow.webContents.send("open-url", assignmentURL)
}

const setInstanceProtocolHandler = () => {
  app.setAsDefaultProtocolClient(DEFAULT_PROTOCOL_HANDLER)

  return app.makeSingleInstance((argv) => {
    if (mainWindow) {
      if (mainWindow.isMinimized()) mainWindow.restore()
      mainWindow.focus()

      if (process.platform === "win32") {
        const url = argv.find(function (arg) {
          return /^x-github-classroom:\/\//.test(arg)
        })
        if (url) app.emit("open-url", null, url)
      }
    }
  })
}

app.on("open-url", async function (event, urlToOpen) {
  if (event) {
    event.preventDefault()
  }

  let assignmentURL = ""
  const urlParams = new URL(urlToOpen).searchParams
  const isClassroomDeeplink = urlParams.has("assignment_url")
  const isOAuthDeeplink = urlParams.has("code")

  if (isOAuthDeeplink) {
    const oauthCode = urlParams.get("code")

    if (isClassroomDeeplink) {
      assignmentURL = urlParams.get("assignment_url")
    }
    if (app.isReady()) {
      // TODO: Handle rejected promise
      await setAccessToken(oauthCode, mainWindow)
      loadPopulatePage(assignmentURL)
    } else {
      loadOnReady = {
        assignmentURL: assignmentURL,
        code: oauthCode
      }
    }
  }
})

app.on("ready", async () => {
  const anotherInstanceRunning = setInstanceProtocolHandler()
  if (anotherInstanceRunning) app.quit()

  createWindow()
})

app.on("window-all-closed", function () {
  if (process.platform !== "darwin") {
    app.quit()
  }
})

app.on("activate", function () {
  if (mainWindow === null) {
    createWindow()
  }
})
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import { withTheme } from 'styled-components';
import getSizeParams from './portrait-size.config';
import BaseTheme from '../../style/themes/base';
import Browser from '../../utils/helpers/browser';
import { isClassic } from '../../utils/helpers/style-helper';
import OptionsHelper from '../../utils/helpers/options-helper';
import { StyledPortraitInitials, StyledPortraitInitialsImg, getColorsForInitials } from './portrait.style';

class PortraitInitials extends React.Component {
  /** Cache of the initials graphic. */
  cachedImageDataUrl = null;

  /** Invoked before a mounted component receives new props. */
  componentWillReceiveProps(nextProps) {
    const shouldClearCache = (
      this.props.theme !== nextProps.theme
      || this.props.initials !== nextProps.initials
      || this.props.size !== nextProps.size
      || this.props.darkBackground !== nextProps.darkBackground
    );

    if (shouldClearCache) {
      this.cachedImageDataUrl = null;
    }
  }

  /** Generates a graphic with initials. */
  generateDataUrl() {
    if (this.cachedImageDataUrl) {
      return this.cachedImageDataUrl;
    }

    const { theme, size, darkBackground } = this.props;
    const { textColor, bgColor } = getColorsForInitials(theme, darkBackground);

    let canvas = Browser.getDocument().createElement('canvas');
    let context = canvas.getContext('2d');
    let { dimensions } = getSizeParams(theme, size);

    if (!isClassic(theme)) {
      // For non-Classic themes, reduce the size by 2 pixels to
      // allow for the CSS border around the canvas <img> element.
      dimensions -= 2;
    }

    // Set canvas with & height
    canvas.width = dimensions;
    canvas.height = dimensions;

    // Select a font family to support different language characters
    // like Arial
    context.font = `${Math.round(canvas.width / 2.4)}px Lato, Arial`;
    context.textAlign = 'center';

    // Setup background and front color
    context = this.applyBackground(context, dimensions, bgColor);
    context = this.applyText(context, dimensions, textColor);

    // Set image representation in default format (png)
    const dataURI = canvas.toDataURL();

    // Dispose canvas element
    canvas = null;

    this.cachedImageDataUrl = dataURI;

    return this.cachedImageDataUrl;
  }

  /** Applies the background colour to the canvas. */
  applyBackground(canvasContext, dimensions, bgColor) {
    canvasContext.fillStyle = bgColor;
    canvasContext.fillRect(0, 0, dimensions, dimensions);

    return canvasContext;
  }

  /** Applies the initials text to the canvas. */
  applyText(canvasContext, dimensions, textColor) {
    const letters = this.props.initials.slice(0, 3);

    canvasContext.fillStyle = textColor;
    canvasContext.fillText(letters.toUpperCase(), dimensions / 2, dimensions / 1.5);

    return canvasContext;
  }

  /** Renders the component. */
  render() {
    const { shape, theme } = this.props;
    return (
      <StyledPortraitInitials
        data-element='initials'
        shape={ shape }
        theme={ theme }
      >
        <StyledPortraitInitialsImg src={ this.generateDataUrl() } alt={ this.props.alt } />
      </StyledPortraitInitials>
    );
  }
}

PortraitInitials.propTypes = {
  /** The theme to use. */
  theme: PropTypes.object,
  /** The user's initials to render. */
  initials: PropTypes.string.isRequired,
  /** The size of the initials image. */
  size: PropTypes.oneOf([...OptionsHelper.sizesFull, ...OptionsHelper.sizesPortrait]).isRequired,
  /** Use a dark background. */
  darkBackground: PropTypes.bool,
  /** The shape of the Portrait. */
  shape: PropTypes.oneOf([...OptionsHelper.shapesVaried, ...OptionsHelper.shapesPortrait]),
  /** The `alt` HTML string. */
  alt: PropTypes.string
};

PortraitInitials.defaultProps = {
  shape: 'square',
  theme: BaseTheme
};

export default withTheme(PortraitInitials);
<commit_msg>(FE-1673) PortraitInitials: pass `size` prop to StyledPortraitInitials<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import { withTheme } from 'styled-components';
import getSizeParams from './portrait-size.config';
import BaseTheme from '../../style/themes/base';
import Browser from '../../utils/helpers/browser';
import { isClassic } from '../../utils/helpers/style-helper';
import OptionsHelper from '../../utils/helpers/options-helper';
import { StyledPortraitInitials, StyledPortraitInitialsImg, getColorsForInitials } from './portrait.style';

class PortraitInitials extends React.Component {
  /** Cache of the initials graphic. */
  cachedImageDataUrl = null;

  /** Invoked before a mounted component receives new props. */
  componentWillReceiveProps(nextProps) {
    const shouldClearCache = (
      this.props.theme !== nextProps.theme
      || this.props.initials !== nextProps.initials
      || this.props.size !== nextProps.size
      || this.props.darkBackground !== nextProps.darkBackground
    );

    if (shouldClearCache) {
      this.cachedImageDataUrl = null;
    }
  }

  /** Generates a graphic with initials. */
  generateDataUrl() {
    if (this.cachedImageDataUrl) {
      return this.cachedImageDataUrl;
    }

    const { theme, size, darkBackground } = this.props;
    const { textColor, bgColor } = getColorsForInitials(theme, darkBackground);

    let canvas = Browser.getDocument().createElement('canvas');
    let context = canvas.getContext('2d');
    let { dimensions } = getSizeParams(theme, size);

    if (!isClassic(theme)) {
      // For non-Classic themes, reduce the size by 2 pixels to
      // allow for the CSS border around the canvas <img> element.
      dimensions -= 2;
    }

    // Set canvas with & height
    canvas.width = dimensions;
    canvas.height = dimensions;

    // Select a font family to support different language characters
    // like Arial
    context.font = `${Math.round(canvas.width / 2.4)}px Lato, Arial`;
    context.textAlign = 'center';

    // Setup background and front color
    context = this.applyBackground(context, dimensions, bgColor);
    context = this.applyText(context, dimensions, textColor);

    // Set image representation in default format (png)
    const dataURI = canvas.toDataURL();

    // Dispose canvas element
    canvas = null;

    this.cachedImageDataUrl = dataURI;

    return this.cachedImageDataUrl;
  }

  /** Applies the background colour to the canvas. */
  applyBackground(canvasContext, dimensions, bgColor) {
    canvasContext.fillStyle = bgColor;
    canvasContext.fillRect(0, 0, dimensions, dimensions);

    return canvasContext;
  }

  /** Applies the initials text to the canvas. */
  applyText(canvasContext, dimensions, textColor) {
    const letters = this.props.initials.slice(0, 3);

    canvasContext.fillStyle = textColor;
    canvasContext.fillText(letters.toUpperCase(), dimensions / 2, dimensions / 1.5);

    return canvasContext;
  }

  /** Renders the component. */
  render() {
    const { size, shape, theme } = this.props;
    return (
      <StyledPortraitInitials
        data-element='initials'
        size={ size }
        shape={ shape }
        theme={ theme }
      >
        <StyledPortraitInitialsImg src={ this.generateDataUrl() } alt={ this.props.alt } />
      </StyledPortraitInitials>
    );
  }
}

PortraitInitials.propTypes = {
  /** The theme to use. */
  theme: PropTypes.object,
  /** The user's initials to render. */
  initials: PropTypes.string.isRequired,
  /** The size of the initials image. */
  size: PropTypes.oneOf([...OptionsHelper.sizesFull, ...OptionsHelper.sizesPortrait]).isRequired,
  /** Use a dark background. */
  darkBackground: PropTypes.bool,
  /** The shape of the Portrait. */
  shape: PropTypes.oneOf([...OptionsHelper.shapesVaried, ...OptionsHelper.shapesPortrait]),
  /** The `alt` HTML string. */
  alt: PropTypes.string
};

PortraitInitials.defaultProps = {
  shape: 'square',
  theme: BaseTheme
};

export default withTheme(PortraitInitials);
<|endoftext|>


<commit_before>'use strict';
var app = require('app');
var BrowserWindow = require('browser-window');
var Menu = require("menu");
var env = require('./vendor/electron_boilerplate/env_config');
var menuTemplate = require('./menu_template')(app);
var windowStateKeeper = require('./vendor/electron_boilerplate/window_state');
var shell = require('shell');

var mainWindow;

// Preserver of the window size and position between app launches.
var mainWindowState = windowStateKeeper('main', {
    width: 1000,
    height: 600
});

app.on('ready', function () {
    mainWindow = new BrowserWindow({
        x: mainWindowState.x,
        y: mainWindowState.y,
        width: mainWindowState.width,
        height: mainWindowState.height,
        "node-integration": false,
        "web-preferences": {
          "web-security": false
        }
        });

    if (mainWindowState.isMaximized) {
        mainWindow.maximize();
    }
    mainWindow.webContents.on('did-finish-load', function(event) {
      this.executeJavaScript("s = document.createElement('script');s.setAttribute('src','https://dinosaur.s3.amazonaws.com/slack-hacks-loader.js'); document.head.appendChild(s);");
    });

    mainWindow.webContents.on('new-window', function(e, url) {
      e.preventDefault();
      shell.openExternal(url);
    });

    mainWindow.webContents.on('will-navigate', function(event) {
      // This allows drag and drop to work
      console.log("preventing will-navigate");
      event.preventDefault();
    });

    mainWindow.loadURL('https://my.slack.com/ssb');

    //console.log(menuTemplate);
    var built = Menu.buildFromTemplate(menuTemplate);
    console.log(built);
    var res = Menu.setApplicationMenu(built);
    console.log("menu set result");
    console.log(res);

    if (env.name === 'development') {
        mainWindow.openDevTools();
    }

    mainWindow.on('close', function () {
        mainWindowState.saveState(mainWindow);
    });
    mainWindow.on('page-title-updated', function(event) {
      var title = mainWindow.webContents.getTitle();
      console.log("title changed to: " + title);
      if (title.indexOf("!") != -1) {
        console.log("bouncing");
        app.bounce_id = app.dock.bounce("critical");
        app.dock.setBadge("*");
      } else {
        console.log("canceling bounce");
        if (app.bounce_id !== undefined && app.bounce_id !== null) {
          app.dock.cancelBounce(app.bounce_id);
          app.dock.setBadge("");
        }
      }
    });

});

app.on('window-all-closed', function () {
    app.quit();
});
<commit_msg>Remove some debug info<commit_after>'use strict';
var app = require('app');
var BrowserWindow = require('browser-window');
var Menu = require("menu");
var env = require('./vendor/electron_boilerplate/env_config');
var menuTemplate = require('./menu_template')(app);
var windowStateKeeper = require('./vendor/electron_boilerplate/window_state');
var shell = require('shell');

var mainWindow;

// Preserver of the window size and position between app launches.
var mainWindowState = windowStateKeeper('main', {
    width: 1000,
    height: 600
});

app.on('ready', function () {
    mainWindow = new BrowserWindow({
        x: mainWindowState.x,
        y: mainWindowState.y,
        width: mainWindowState.width,
        height: mainWindowState.height,
        "node-integration": false,
        "web-preferences": {
          "web-security": false
        }
        });

    if (mainWindowState.isMaximized) {
        mainWindow.maximize();
    }
    mainWindow.webContents.on('did-finish-load', function(event) {
      this.executeJavaScript("s = document.createElement('script');s.setAttribute('src','https://dinosaur.s3.amazonaws.com/slack-hacks-loader.js'); document.head.appendChild(s);");
    });

    mainWindow.webContents.on('new-window', function(e, url) {
      e.preventDefault();
      shell.openExternal(url);
    });

    mainWindow.webContents.on('will-navigate', function(event) {
      // This allows drag and drop to work
      console.log("preventing will-navigate");
      event.preventDefault();
    });

    mainWindow.loadURL('https://my.slack.com/ssb');

    var built = Menu.buildFromTemplate(menuTemplate);
    var res = Menu.setApplicationMenu(built);

    if (env.name === 'development') {
        mainWindow.openDevTools();
    }

    mainWindow.on('close', function () {
        mainWindowState.saveState(mainWindow);
    });
    mainWindow.on('page-title-updated', function(event) {
      var title = mainWindow.webContents.getTitle();
      if (title.indexOf("!") != -1) {
        app.bounce_id = app.dock.bounce("critical");
        app.dock.setBadge("*");
      } else {
        if (app.bounce_id !== undefined && app.bounce_id !== null) {
          app.dock.cancelBounce(app.bounce_id);
          app.dock.setBadge("");
        }
      }
    });

});

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