<commit_before>import Declaration from './declaration';
import tokenizer   from './tokenize';
import Comment     from './comment';
import AtRule      from './at-rule';
import Root        from './root';
import Rule        from './rule';

export default class Parser {

    constructor(input) {
        this.input = input;

        this.root      = new Root();
        this.current   = this.root;
        this.spaces    = '';
        this.semicolon = false;

        this.tokenizer = tokenizer(this.input);

        this.root.source = { input, start: { line: 1, column: 1 } };
    }

    parse() {
        let token;
        while ( !this.tokenizer.endOfFile() ) {
            token = this.tokenizer.nextToken();

            switch ( token[0] ) {

            case 'space':
                this.spaces += token[1];
                break;

            case ';':
                this.freeSemicolon(token);
                break;

            case '}':
                this.end(token);
                break;

            case 'comment':
                this.comment(token);
                break;

            case 'at-word':
                this.atrule(token);
                break;

            case '{':
                this.emptyRule(token);
                break;

            default:
                this.other(token);
                break;
            }
        }
        this.endFile();
    }

    comment(token) {
        let node = new Comment();
        this.init(node, token[2], token[3]);
        node.source.end = { line: token[4], column: token[5] };

        let text = token[1].slice(2, -2);
        if ( /^\s*$/.test(text) ) {
            node.text       = '';
            node.raws.left  = text;
            node.raws.right = '';
        } else {
            let match = text.match(/^(\s*)([^]*[^\s])(\s*)$/);
            node.text       = match[2];
            node.raws.left  = match[1];
            node.raws.right = match[3];
        }
    }

    emptyRule(token) {
        let node = new Rule();
        this.init(node, token[2], token[3]);
        node.selector = '';
        node.raws.between = '';
        this.current = node;
    }

    other(start) {
        let end      = false;
        let type     = null;
        let colon    = false;
        let bracket  = null;
        let brackets = [];

        let tokens = [];
        let token = start;
        while ( token ) {
            type = token[0];
            tokens.push(token);

            if ( type === '(' || type === '[' ) {
                if ( !bracket ) bracket = token;
                brackets.push(type === '(' ? ')' : ']');

            } else if ( brackets.length === 0 ) {
                if ( type === ';' ) {
                    if ( colon ) {
                        this.decl(tokens);
                        return;
                    } else {
                        break;
                    }

                } else if ( type === '{' ) {
                    this.rule(tokens);
                    return;

                } else if ( type === '}' ) {
                    this.tokenizer.back(tokens.pop());
                    end = true;
                    break;

                } else if ( type === ':' ) {
                    colon = true;
                }

            } else if ( type === brackets[brackets.length - 1] ) {
                brackets.pop();
                if ( brackets.length === 0 ) bracket = null;
            }

            token = this.tokenizer.nextToken();
        }

        if ( this.tokenizer.endOfFile() ) end = true;
        if ( brackets.length > 0 ) this.unclosedBracket(bracket);

        if ( end && colon ) {
            while ( tokens.length ) {
                token = tokens[tokens.length - 1][0];
                if ( token !== 'space' && token !== 'comment' ) break;
                this.tokenizer.back(tokens.pop());
            }
            this.decl(tokens);
            return;
        } else {
            this.unknownWord(start);
        }
    }

    rule(tokens) {
        tokens.pop();

        let node = new Rule();
        this.init(node, tokens[0][2], tokens[0][3]);

        node.raws.between = this.spacesAndCommentsFromEnd(tokens);
        this.raw(node, 'selector', tokens);
        this.current = node;
    }

    decl(tokens) {
        let node = new Declaration();
        this.init(node);

        let last = tokens[tokens.length - 1];
        if ( last[0] === ';' ) {
            this.semicolon = true;
            tokens.pop();
        }
        if ( last[4] ) {
            node.source.end = { line: last[4], column: last[5] };
        } else {
            node.source.end = { line: last[2], column: last[3] };
        }

        while ( tokens[0][0] !== 'word' ) {
            if ( tokens.length === 1 ) this.unknownWord(tokens[0]);
            node.raws.before += tokens.shift()[1];
        }
        node.source.start = { line: tokens[0][2], column: tokens[0][3] };

        node.prop = '';
        while ( tokens.length ) {
            let type = tokens[0][0];
            if ( type === ':' || type === 'space' || type === 'comment' ) {
                break;
            }
            node.prop += tokens.shift()[1];
        }

        node.raws.between = '';

        let token;
        while ( tokens.length ) {
            token = tokens.shift();

            if ( token[0] === ':' ) {
                node.raws.between += token[1];
                break;
            } else {
                node.raws.between += token[1];
            }
        }

        if ( node.prop[0] === '_' || node.prop[0] === '*' ) {
            node.raws.before += node.prop[0];
            node.prop = node.prop.slice(1);
        }
        node.raws.between += this.spacesAndCommentsFromStart(tokens);
        this.precheckMissedSemicolon(tokens);

        for ( let i = tokens.length - 1; i > 0; i-- ) {
            token = tokens[i];
            if ( token[1] === '!important' ) {
                node.important = true;
                let string = this.stringFrom(tokens, i);
                string = this.spacesFromEnd(tokens) + string;
                if ( string !== ' !important' ) node.raws.important = string;
                break;

            } else if (token[1] === 'important') {
                let cache = tokens.slice(0);
                let str   = '';
                for ( let j = i; j > 0; j-- ) {
                    let type = cache[j][0];
                    if ( str.trim().indexOf('!') === 0 && type !== 'space' ) {
                        break;
                    }
                    str = cache.pop()[1] + str;
                }
                if ( str.trim().indexOf('!') === 0 ) {
                    node.important = true;
                    node.raws.important = str;
                    tokens = cache;
                }
            }

            if ( token[0] !== 'space' && token[0] !== 'comment' ) {
                break;
            }
        }

        this.raw(node, 'value', tokens);

        if ( node.value.indexOf(':') !== -1 ) this.checkMissedSemicolon(tokens);
    }

    atrule(token) {
        let node  = new AtRule();
        node.name = token[1].slice(1);
        if ( node.name === '' ) {
            this.unnamedAtrule(node, token);
        }
        this.init(node, token[2], token[3]);

        let last   = false;
        let open   = false;
        let params = [];

        while ( !this.tokenizer.endOfFile() ) {
            token = this.tokenizer.nextToken();

            if ( token[0] === ';' ) {
                node.source.end = { line: token[2], column: token[3] };
                this.semicolon = true;
                break;
            } else if ( token[0] === '{' ) {
                open = true;
                break;
            } else if ( token[0] === '}') {
                this.end(token);
                break;
            } else {
                params.push(token);
            }

            if ( this.tokenizer.endOfFile() ) {
                last = true;
                break;
            }
        }

        node.raws.between = this.spacesAndCommentsFromEnd(params);
        if ( params.length ) {
            node.raws.afterName = this.spacesAndCommentsFromStart(params);
            this.raw(node, 'params', params);
            if ( last ) {
                token = params[params.length - 1];
                node.source.end   = { line: token[4], column: token[5] };
                this.spaces       = node.raws.between;
                node.raws.between = '';
            }
        } else {
            node.raws.afterName = '';
            node.params         = '';
        }

        if ( open ) {
            node.nodes   = [];
            this.current = node;
        }
    }

    end(token) {
        if ( this.current.nodes && this.current.nodes.length ) {
            this.current.raws.semicolon = this.semicolon;
        }
        this.semicolon = false;

        this.current.raws.after = (this.current.raws.after || '') + this.spaces;
        this.spaces = '';

        if ( this.current.parent ) {
            this.current.source.end = { line: token[2], column: token[3] };
            this.current = this.current.parent;
        } else {
            this.unexpectedClose(token);
        }
    }

    endFile() {
        if ( this.current.parent ) this.unclosedBlock();
        if ( this.current.nodes && this.current.nodes.length ) {
            this.current.raws.semicolon = this.semicolon;
        }
        this.current.raws.after = (this.current.raws.after || '') + this.spaces;
    }

    freeSemicolon(token) {
        this.spaces += token[1];
        if ( this.current.nodes ) {
            let prev = this.current.nodes[this.current.nodes.length - 1];
            if ( prev && prev.type === 'rule' ) {
                prev.raws.ownSemicolon = this.spaces;
                this.spaces = '';
            }
        }
    }

    // Helpers

    init(node, line, column) {
        this.current.push(node);

        node.source = { start: { line, column }, input: this.input };
        node.raws.before = this.spaces;
        this.spaces = '';
        if ( node.type !== 'comment' ) this.semicolon = false;
    }

    raw(node, prop, tokens) {
        let token, type;
        let length = tokens.length;
        let value  = '';
        let clean  = true;
        for ( let i = 0; i < length; i += 1 ) {
            token = tokens[i];
            type  = token[0];
            if ( type === 'comment' || type === 'space' && i === length - 1 ) {
                clean = false;
            } else {
                value += token[1];
            }
        }
        if ( !clean ) {
            let raw = tokens.reduce( (all, i) => all + i[1], '');
            node.raws[prop] = { value, raw };
        }
        node[prop] = value;
    }

    spacesAndCommentsFromEnd(tokens) {
        let lastTokenType;
        let spaces = '';
        while ( tokens.length ) {
            lastTokenType = tokens[tokens.length - 1][0];
            if ( lastTokenType !== 'space' &&
                lastTokenType !== 'comment' ) break;
            spaces = tokens.pop()[1] + spaces;
        }
        return spaces;
    }

    spacesAndCommentsFromStart(tokens) {
        let next;
        let spaces = '';
        while ( tokens.length ) {
            next = tokens[0][0];
            if ( next !== 'space' && next !== 'comment' ) break;
            spaces += tokens.shift()[1];
        }
        return spaces;
    }

    spacesFromEnd(tokens) {
        let lastTokenType;
        let spaces = '';
        while ( tokens.length ) {
            lastTokenType = tokens[tokens.length - 1][0];
            if ( lastTokenType !== 'space' ) break;
            spaces = tokens.pop()[1] + spaces;
        }
        return spaces;
    }

    stringFrom(tokens, from) {
        let result = '';
        for ( let i = from; i < tokens.length; i++ ) {
            result += tokens[i][1];
        }
        tokens.splice(from, tokens.length - from);
        return result;
    }

    colon(tokens) {
        let brackets = 0;
        let token, type, prev;
        for ( let i = 0; i < tokens.length; i++ ) {
            token = tokens[i];
            type  = token[0];

            if ( type === '(' ) {
                brackets += 1;
            } else if ( type === ')' ) {
                brackets -= 1;
            } else if ( brackets === 0 && type === ':' ) {
                if ( !prev ) {
                    this.doubleColon(token);
                } else if ( prev[0] === 'word' && prev[1] === 'progid' ) {
                    continue;
                } else {
                    return i;
                }
            }

            prev = token;
        }
        return false;
    }

    // Errors

    unclosedBracket(bracket) {
        throw this.input.error('Unclosed bracket', bracket[2], bracket[3]);
    }

    unknownWord(token) {
        throw this.input.error('Unknown word', token[2], token[3]);
    }

    unexpectedClose(token) {
        throw this.input.error('Unexpected }', token[2], token[3]);
    }

    unclosedBlock() {
        let pos = this.current.source.start;
        throw this.input.error('Unclosed block', pos.line, pos.column);
    }

    doubleColon(token) {
        throw this.input.error('Double colon', token[2], token[3]);
    }

    unnamedAtrule(node, token) {
        throw this.input.error('At-rule without name', token[2], token[3]);
    }

    precheckMissedSemicolon(tokens) {
        // Hook for Safe Parser
        tokens;
    }

    checkMissedSemicolon(tokens) {
        let colon = this.colon(tokens);
        if ( colon === false ) return;

        let founded = 0;
        let token;
        for ( let j = colon - 1; j >= 0; j-- ) {
            token = tokens[j];
            if ( token[0] !== 'space' ) {
                founded += 1;
                if ( founded === 2 ) break;
            }
        }
        throw this.input.error('Missed semicolon', token[2], token[3]);
    }

}
<commit_msg>Send all tokens to Parser#unknownWord<commit_after>import Declaration from './declaration';
import tokenizer   from './tokenize';
import Comment     from './comment';
import AtRule      from './at-rule';
import Root        from './root';
import Rule        from './rule';

export default class Parser {

    constructor(input) {
        this.input = input;

        this.root      = new Root();
        this.current   = this.root;
        this.spaces    = '';
        this.semicolon = false;

        this.tokenizer = tokenizer(this.input);

        this.root.source = { input, start: { line: 1, column: 1 } };
    }

    parse() {
        let token;
        while ( !this.tokenizer.endOfFile() ) {
            token = this.tokenizer.nextToken();

            switch ( token[0] ) {

            case 'space':
                this.spaces += token[1];
                break;

            case ';':
                this.freeSemicolon(token);
                break;

            case '}':
                this.end(token);
                break;

            case 'comment':
                this.comment(token);
                break;

            case 'at-word':
                this.atrule(token);
                break;

            case '{':
                this.emptyRule(token);
                break;

            default:
                this.other(token);
                break;
            }
        }
        this.endFile();
    }

    comment(token) {
        let node = new Comment();
        this.init(node, token[2], token[3]);
        node.source.end = { line: token[4], column: token[5] };

        let text = token[1].slice(2, -2);
        if ( /^\s*$/.test(text) ) {
            node.text       = '';
            node.raws.left  = text;
            node.raws.right = '';
        } else {
            let match = text.match(/^(\s*)([^]*[^\s])(\s*)$/);
            node.text       = match[2];
            node.raws.left  = match[1];
            node.raws.right = match[3];
        }
    }

    emptyRule(token) {
        let node = new Rule();
        this.init(node, token[2], token[3]);
        node.selector = '';
        node.raws.between = '';
        this.current = node;
    }

    other(start) {
        let end      = false;
        let type     = null;
        let colon    = false;
        let bracket  = null;
        let brackets = [];

        let tokens = [];
        let token = start;
        while ( token ) {
            type = token[0];
            tokens.push(token);

            if ( type === '(' || type === '[' ) {
                if ( !bracket ) bracket = token;
                brackets.push(type === '(' ? ')' : ']');

            } else if ( brackets.length === 0 ) {
                if ( type === ';' ) {
                    if ( colon ) {
                        this.decl(tokens);
                        return;
                    } else {
                        break;
                    }

                } else if ( type === '{' ) {
                    this.rule(tokens);
                    return;

                } else if ( type === '}' ) {
                    this.tokenizer.back(tokens.pop());
                    end = true;
                    break;

                } else if ( type === ':' ) {
                    colon = true;
                }

            } else if ( type === brackets[brackets.length - 1] ) {
                brackets.pop();
                if ( brackets.length === 0 ) bracket = null;
            }

            token = this.tokenizer.nextToken();
        }

        if ( this.tokenizer.endOfFile() ) end = true;
        if ( brackets.length > 0 ) this.unclosedBracket(bracket);

        if ( end && colon ) {
            while ( tokens.length ) {
                token = tokens[tokens.length - 1][0];
                if ( token !== 'space' && token !== 'comment' ) break;
                this.tokenizer.back(tokens.pop());
            }
            this.decl(tokens);
            return;
        } else {
            this.unknownWord(tokens);
        }
    }

    rule(tokens) {
        tokens.pop();

        let node = new Rule();
        this.init(node, tokens[0][2], tokens[0][3]);

        node.raws.between = this.spacesAndCommentsFromEnd(tokens);
        this.raw(node, 'selector', tokens);
        this.current = node;
    }

    decl(tokens) {
        let node = new Declaration();
        this.init(node);

        let last = tokens[tokens.length - 1];
        if ( last[0] === ';' ) {
            this.semicolon = true;
            tokens.pop();
        }
        if ( last[4] ) {
            node.source.end = { line: last[4], column: last[5] };
        } else {
            node.source.end = { line: last[2], column: last[3] };
        }

        while ( tokens[0][0] !== 'word' ) {
            if ( tokens.length === 1 ) this.unknownWord(tokens);
            node.raws.before += tokens.shift()[1];
        }
        node.source.start = { line: tokens[0][2], column: tokens[0][3] };

        node.prop = '';
        while ( tokens.length ) {
            let type = tokens[0][0];
            if ( type === ':' || type === 'space' || type === 'comment' ) {
                break;
            }
            node.prop += tokens.shift()[1];
        }

        node.raws.between = '';

        let token;
        while ( tokens.length ) {
            token = tokens.shift();

            if ( token[0] === ':' ) {
                node.raws.between += token[1];
                break;
            } else {
                node.raws.between += token[1];
            }
        }

        if ( node.prop[0] === '_' || node.prop[0] === '*' ) {
            node.raws.before += node.prop[0];
            node.prop = node.prop.slice(1);
        }
        node.raws.between += this.spacesAndCommentsFromStart(tokens);
        this.precheckMissedSemicolon(tokens);

        for ( let i = tokens.length - 1; i > 0; i-- ) {
            token = tokens[i];
            if ( token[1] === '!important' ) {
                node.important = true;
                let string = this.stringFrom(tokens, i);
                string = this.spacesFromEnd(tokens) + string;
                if ( string !== ' !important' ) node.raws.important = string;
                break;

            } else if (token[1] === 'important') {
                let cache = tokens.slice(0);
                let str   = '';
                for ( let j = i; j > 0; j-- ) {
                    let type = cache[j][0];
                    if ( str.trim().indexOf('!') === 0 && type !== 'space' ) {
                        break;
                    }
                    str = cache.pop()[1] + str;
                }
                if ( str.trim().indexOf('!') === 0 ) {
                    node.important = true;
                    node.raws.important = str;
                    tokens = cache;
                }
            }

            if ( token[0] !== 'space' && token[0] !== 'comment' ) {
                break;
            }
        }

        this.raw(node, 'value', tokens);

        if ( node.value.indexOf(':') !== -1 ) this.checkMissedSemicolon(tokens);
    }

    atrule(token) {
        let node  = new AtRule();
        node.name = token[1].slice(1);
        if ( node.name === '' ) {
            this.unnamedAtrule(node, token);
        }
        this.init(node, token[2], token[3]);

        let last   = false;
        let open   = false;
        let params = [];

        while ( !this.tokenizer.endOfFile() ) {
            token = this.tokenizer.nextToken();

            if ( token[0] === ';' ) {
                node.source.end = { line: token[2], column: token[3] };
                this.semicolon = true;
                break;
            } else if ( token[0] === '{' ) {
                open = true;
                break;
            } else if ( token[0] === '}') {
                this.end(token);
                break;
            } else {
                params.push(token);
            }

            if ( this.tokenizer.endOfFile() ) {
                last = true;
                break;
            }
        }

        node.raws.between = this.spacesAndCommentsFromEnd(params);
        if ( params.length ) {
            node.raws.afterName = this.spacesAndCommentsFromStart(params);
            this.raw(node, 'params', params);
            if ( last ) {
                token = params[params.length - 1];
                node.source.end   = { line: token[4], column: token[5] };
                this.spaces       = node.raws.between;
                node.raws.between = '';
            }
        } else {
            node.raws.afterName = '';
            node.params         = '';
        }

        if ( open ) {
            node.nodes   = [];
            this.current = node;
        }
    }

    end(token) {
        if ( this.current.nodes && this.current.nodes.length ) {
            this.current.raws.semicolon = this.semicolon;
        }
        this.semicolon = false;

        this.current.raws.after = (this.current.raws.after || '') + this.spaces;
        this.spaces = '';

        if ( this.current.parent ) {
            this.current.source.end = { line: token[2], column: token[3] };
            this.current = this.current.parent;
        } else {
            this.unexpectedClose(token);
        }
    }

    endFile() {
        if ( this.current.parent ) this.unclosedBlock();
        if ( this.current.nodes && this.current.nodes.length ) {
            this.current.raws.semicolon = this.semicolon;
        }
        this.current.raws.after = (this.current.raws.after || '') + this.spaces;
    }

    freeSemicolon(token) {
        this.spaces += token[1];
        if ( this.current.nodes ) {
            let prev = this.current.nodes[this.current.nodes.length - 1];
            if ( prev && prev.type === 'rule' ) {
                prev.raws.ownSemicolon = this.spaces;
                this.spaces = '';
            }
        }
    }

    // Helpers

    init(node, line, column) {
        this.current.push(node);

        node.source = { start: { line, column }, input: this.input };
        node.raws.before = this.spaces;
        this.spaces = '';
        if ( node.type !== 'comment' ) this.semicolon = false;
    }

    raw(node, prop, tokens) {
        let token, type;
        let length = tokens.length;
        let value  = '';
        let clean  = true;
        for ( let i = 0; i < length; i += 1 ) {
            token = tokens[i];
            type  = token[0];
            if ( type === 'comment' || type === 'space' && i === length - 1 ) {
                clean = false;
            } else {
                value += token[1];
            }
        }
        if ( !clean ) {
            let raw = tokens.reduce( (all, i) => all + i[1], '');
            node.raws[prop] = { value, raw };
        }
        node[prop] = value;
    }

    spacesAndCommentsFromEnd(tokens) {
        let lastTokenType;
        let spaces = '';
        while ( tokens.length ) {
            lastTokenType = tokens[tokens.length - 1][0];
            if ( lastTokenType !== 'space' &&
                lastTokenType !== 'comment' ) break;
            spaces = tokens.pop()[1] + spaces;
        }
        return spaces;
    }

    spacesAndCommentsFromStart(tokens) {
        let next;
        let spaces = '';
        while ( tokens.length ) {
            next = tokens[0][0];
            if ( next !== 'space' && next !== 'comment' ) break;
            spaces += tokens.shift()[1];
        }
        return spaces;
    }

    spacesFromEnd(tokens) {
        let lastTokenType;
        let spaces = '';
        while ( tokens.length ) {
            lastTokenType = tokens[tokens.length - 1][0];
            if ( lastTokenType !== 'space' ) break;
            spaces = tokens.pop()[1] + spaces;
        }
        return spaces;
    }

    stringFrom(tokens, from) {
        let result = '';
        for ( let i = from; i < tokens.length; i++ ) {
            result += tokens[i][1];
        }
        tokens.splice(from, tokens.length - from);
        return result;
    }

    colon(tokens) {
        let brackets = 0;
        let token, type, prev;
        for ( let i = 0; i < tokens.length; i++ ) {
            token = tokens[i];
            type  = token[0];

            if ( type === '(' ) {
                brackets += 1;
            } else if ( type === ')' ) {
                brackets -= 1;
            } else if ( brackets === 0 && type === ':' ) {
                if ( !prev ) {
                    this.doubleColon(token);
                } else if ( prev[0] === 'word' && prev[1] === 'progid' ) {
                    continue;
                } else {
                    return i;
                }
            }

            prev = token;
        }
        return false;
    }

    // Errors

    unclosedBracket(bracket) {
        throw this.input.error('Unclosed bracket', bracket[2], bracket[3]);
    }

    unknownWord(tokens) {
        throw this.input.error('Unknown word', tokens[0][2], tokens[0][3]);
    }

    unexpectedClose(token) {
        throw this.input.error('Unexpected }', token[2], token[3]);
    }

    unclosedBlock() {
        let pos = this.current.source.start;
        throw this.input.error('Unclosed block', pos.line, pos.column);
    }

    doubleColon(token) {
        throw this.input.error('Double colon', token[2], token[3]);
    }

    unnamedAtrule(node, token) {
        throw this.input.error('At-rule without name', token[2], token[3]);
    }

    precheckMissedSemicolon(tokens) {
        // Hook for Safe Parser
        tokens;
    }

    checkMissedSemicolon(tokens) {
        let colon = this.colon(tokens);
        if ( colon === false ) return;

        let founded = 0;
        let token;
        for ( let j = colon - 1; j >= 0; j-- ) {
            token = tokens[j];
            if ( token[0] !== 'space' ) {
                founded += 1;
                if ( founded === 2 ) break;
            }
        }
        throw this.input.error('Missed semicolon', token[2], token[3]);
    }

}
<|endoftext|>


<commit_before>import React from 'react';
import {
  ActivityIndicator,
  FlatList,
  StyleSheet,
  Text,
  View,
} from 'react-native';

import { List, ListItem } from 'react-native-elements'

import HubOnboarding, { WifiConnectionState } from '../HubOnboarding'
import Screen from './Screen';
import Settings from '../Settings'

export default class SetupWifi extends Screen {
  constructor(props) {
    super(props)

    this.state = {
      ssids: [],
      currentSsid: null,
    }

    this.setTitle('Wi-Fi')
  }

  didAppear() {
    let subscribeForWifiEvents = () => {
      HubOnboarding.hubDevice.onNetworksChanged((ssid) => {
        if (!this.state.ssids.find(s => s === ssid)) {
          this.setState({ssids: this.state.ssids
            .concat([ssid])
            .sort(function (a, b) {
              return a.toLowerCase().localeCompare(b.toLowerCase());
            })
          })
        }
      })

      HubOnboarding.hubDevice.onConnectionStateChanged((connectionState, currentSsid) => {
        if (connectionState === WifiConnectionState.CONNECTION_STATE_CONNECTED) {
          this.setState({currentSsid: currentSsid})
        }
      })
    }

    HubOnboarding.hubDevice
      .connect()
      .then(() => {
        subscribeForWifiEvents()
      })
      .catch((error) => {
        alert("Could not connect to the Hub. Please try again.")
        //TODO: Present error message on screen with a "retry" button that connects again
      })
  }

  willDisappear() {
    //TODO: Setting an empty callback isn't clean – use proper approach.
    HubOnboarding.hubDevice.onNetworksChanged(() => {})
    HubOnboarding.hubDevice.onConnectionStateChanged(() => {})
  }

  onNetworkSelected(ssid) {
    console.log("Network selected: " + ssid)

    if (ssid == this.state.currentSsid) {
      Settings.setHubApiUrl(HubOnboarding.hubDevice.dnsName)
        .then(() => this.pushScreen('setup.nuimo'))
    }
    else {
      HubOnboarding.hubDevice.sendSsid(ssid)
      this.pushScreen('setup.wifiPassword') // TODO make it a modal
    }
  }

  render() {
    return (
      <View style={styles.container}>
        {this._renderContent()}
      </View>
    );
  }

  _renderContent() {
    if (this.state.ssids.length > 0) {
      return (
        <View>
          <Text style={styles.title}>
            Select your Wi-Fi network
          </Text>
          <List>
            <FlatList
              data={this.state.ssids}
              renderItem={({item}) => (
                <ListItem title={item}
                  onPress={() => this.onNetworkSelected(item)}
                  leftIcon={this.state.currentSsid == item ? {name: 'done'} : {name: 'wifi'}}
                />
              )}
              keyExtractor={(item) => item}
            />
          </List>
        </View>
      )
    }
    else {
      return (
        <View>
          <Text style={styles.title}>Searching for Wi-Fi networks...</Text>
          <ActivityIndicator size={"large"} />
        </View>
      )
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  title: {
    fontSize: 18,
    textAlign: 'center',
    margin: 10,
  },
})
<commit_msg>Remove title to fix the list out-of-screen issue on iOS<commit_after>import React from 'react';
import {
  ActivityIndicator,
  FlatList,
  StyleSheet,
  Text,
  View,
} from 'react-native';

import { List, ListItem } from 'react-native-elements'

import HubOnboarding, { WifiConnectionState } from '../HubOnboarding'
import Screen from './Screen';
import Settings from '../Settings'

export default class SetupWifi extends Screen {
  constructor(props) {
    super(props)

    this.state = {
      ssids: [],
      currentSsid: null,
    }

    this.setTitle('Select your Wi-Fi')
  }

  didAppear() {
    let subscribeForWifiEvents = () => {
      HubOnboarding.hubDevice.onNetworksChanged((ssid) => {
        if (!this.state.ssids.find(s => s === ssid)) {
          this.setState({ssids: this.state.ssids
            .concat([ssid])
            .sort(function (a, b) {
              return a.toLowerCase().localeCompare(b.toLowerCase());
            })
          })
        }
      })

      HubOnboarding.hubDevice.onConnectionStateChanged((connectionState, currentSsid) => {
        if (connectionState === WifiConnectionState.CONNECTION_STATE_CONNECTED) {
          this.setState({currentSsid: currentSsid})
        }
      })
    }

    HubOnboarding.hubDevice
      .connect()
      .then(() => {
        subscribeForWifiEvents()
      })
      .catch((error) => {
        alert("Could not connect to the Hub. Please try again.")
        //TODO: Present error message on screen with a "retry" button that connects again
      })
  }

  willDisappear() {
    //TODO: Setting an empty callback isn't clean – use proper approach.
    HubOnboarding.hubDevice.onNetworksChanged(() => {})
    HubOnboarding.hubDevice.onConnectionStateChanged(() => {})
  }

  onNetworkSelected(ssid) {
    console.log("Network selected: " + ssid)

    if (ssid == this.state.currentSsid) {
      Settings.setHubApiUrl(HubOnboarding.hubDevice.dnsName)
        .then(() => this.pushScreen('setup.nuimo'))
    }
    else {
      HubOnboarding.hubDevice.sendSsid(ssid)
      this.pushScreen('setup.wifiPassword') // TODO make it a modal
    }
  }

  render() {
    return (
      <View style={styles.container}>
        {this._renderContent()}
      </View>
    );
  }

  _renderContent() {
    if (this.state.ssids.length > 0) {
      return (
        <List>
          <FlatList
            data={this.state.ssids}
            renderItem={({item}) => (
              <ListItem title={item}
                onPress={() => this.onNetworkSelected(item)}
                leftIcon={this.state.currentSsid == item ? {name: 'done'} : {name: 'wifi'}}
              />
            )}
            keyExtractor={(item) => item}
          />
        </List>
      )
    }
    else {
      return (
        <View>
          <Text style={styles.title}>Searching for Wi-Fi networks...</Text>
          <ActivityIndicator size={"large"} />
        </View>
      )
    }
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  title: {
    fontSize: 18,
    textAlign: 'center',
    margin: 10,
  },
})
<|endoftext|>


<commit_before>function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function scroll2bottom() {
  let docHeight = 0;
  while (docHeight < window.document.body.scrollHeight) {
    docHeight = window.document.body.scrollHeight;
    window.scrollTo(0, docHeight);
    await sleep(2000);
  }
}

scroll2bottom();<commit_msg>fixed scroll2bottom script<commit_after>function sleep(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function scroll2bottom() {
  let docHeight = 0;
  let delay = 500;
  while (docHeight < window.document.body.scrollHeight) {
    docHeight = window.document.body.scrollHeight;
    window.scrollTo(0, docHeight);
    await sleep(delay);
    if (docHeight == window.document.body.scrollHeight) {
      delay += 500;
      await sleep(3000);
    }
  }
}

scroll2bottom();<|endoftext|>


<commit_before>(function(){
	window.TAG_CONFIG = {
		'input-id' : 'input',			    //输入标签的id
		'ul-id' : 'tag_ul',				    //下拉ul的id
		'tag-div-id' : 'tag-content',       //放tag-span的div的id
		'input-div-id' : 'tag_input',       //放输入标签的input与ul的div的id，如无id冲突无需更改
		'input-name':  'tags',			    //提交时后台接收参数时的name值
		'tag-join': '-',				    //tags的分隔符，默认 A-B-C
		'tag-api':'./ajax.php',    		    //获取已存在标签地址
		'max-tags': 5,				        //最大标签数，当为0时无限制
		'max-select' : 5,			        //li中最多显示几个备选词
		'max-tag-length': 20,               //单个标签长度限制
		'ajax-type' : 'GET',                //xhr请求方式
		'li-class-name': 'tag-on',          //li类名称，绑定事件所用
		'tag-span-class-name': 'tag-items', //放标签的span类名，绑定事件所用
		'strict-fillter': true,             //严格过滤模式，开启则禁止规则符号输入
		'fillter' : true,                   //正则过滤模式
		'span-border-color': '#98FB98',     //标签边框颜色
		'span-color':'#FFF',                //标签颜色
		'span-mouse-over-color' : '#98FB98',//标签鼠标选中时的颜色
		'tag-font':'sans-serif',            //标签字体
		'allow-rule': /^[\w\.]{1,20}$/,      //正则过滤规则
		'error-msg': 'dis-allow-rule',      //过滤模式错误信息
		'dis-allow-char': ['.','Process','+','=','(',')','*','&','%',' ','，','。',],  //禁止输入字符(字符，不是汉字)
	}
})()<commit_msg>更改规则默认可以识别中文<commit_after>(function(){
	window.TAG_CONFIG = {
		'input-id' : 'input',			    //输入标签的id
		'ul-id' : 'tag_ul',				    //下拉ul的id
		'tag-div-id' : 'tag-content',       //放tag-span的div的id
		'input-div-id' : 'tag_input',       //放输入标签的input与ul的div的id，如无id冲突无需更改
		'input-name':  'tags',			    //提交时后台接收参数时的name值
		'tag-join': '-',				    //tags的分隔符，默认 A-B-C
		'tag-api':'./ajax.php',    		    //获取已存在标签地址
		'max-tags': 5,				        //最大标签数，当为0时无限制
		'max-select' : 5,			        //li中最多显示几个备选词
		'max-tag-length': 20,               //单个标签长度限制
		'ajax-type' : 'GET',                //xhr请求方式
		'li-class-name': 'tag-on',          //li类名称，绑定事件所用
		'tag-span-class-name': 'tag-items', //放标签的span类名，绑定事件所用
		'strict-fillter': false,             //严格过滤模式，开启则禁止规则符号输入
		'fillter' : true,                   //正则过滤模式
		'span-border-color': '#98FB98',     //标签边框颜色
		'span-color':'#FFF',                //标签颜色
		'span-mouse-over-color' : '#98FB98',//标签鼠标选中时的颜色
		'tag-font':'sans-serif',            //标签字体
		'allow-rule': /^[\w\.\u4e00-\u9fa5]{1,20}$/,      //正则过滤规则
		'error-msg': 'dis-allow-rule',      //过滤模式错误信息
		'dis-allow-char': ['.','Process','+','=','(',')','*','&','%',' ','，','。',],  //禁止输入字符(字符，不是汉字)
	}
})()<|endoftext|>


<commit_before>var columnDefs = [
    { field: "country", width: 150, chartDataType: 'category' },
    { field: "gold", chartDataType: 'series' },
    { field: "silver", chartDataType: 'series' },
    { field: "bronze", chartDataType: 'series' },
    { headerName: "A", valueGetter: 'Math.floor(Math.random()*1000)', chartDataType: 'series' },
    { headerName: "B", valueGetter: 'Math.floor(Math.random()*1000)', chartDataType: 'series' },
    { headerName: "C", valueGetter: 'Math.floor(Math.random()*1000)', chartDataType: 'series' },
    { headerName: "D", valueGetter: 'Math.floor(Math.random()*1000)', chartDataType: 'series' }
];

var gridOptions = {
    defaultColDef: {
        editable: true,
        sortable: true,
        flex: 1,
        minWidth: 100,
        filter: true,
        resizable: true
    },
    columnDefs: columnDefs,
    rowData: createRowData(),
    popupParent: document.body,
    enableCharts: true,
    enableRangeSelection: true,
    onFirstDataRendered: onFirstDataRendered,
    processChartOptions: processChartOptions,
    getChartToolbarItems: getChartToolbarItems
};

function getChartToolbarItems() {
    return ['chartDownload', 'chartData', 'chartSettings'];
}

function onFirstDataRendered(params) {
    var createRangeChartParams = {
        cellRange: {
            rowStartIndex: 0,
            rowEndIndex: 4,
            columns: ['country', 'gold']
        },
        chartType: 'pie'
    };

    params.api.createRangeChart(createRangeChartParams);
}

function processChartOptions(params) {
    var options = params.options;

    if (params.type === 'pie') {
        options.title = {
            enabled: true,
            text: 'Precious Metals Production',
            fontFamily: 'Verdana, sans-serif',
            fontWeight: 'bold',
            fontSize: 20,
            color: 'rgb(100, 100, 100)'
        };

        options.subtitle = {
            enabled: true,
            text: 'by country',
            fontFamily: 'Verdana, sans-serif',
            fontStyle: 'italic',
            fontWeight: 'bold',
            fontSize: 14,
            color: 'rgb(100, 100, 100)'
        };

        options.padding = { top: 25, right: 20, bottom: 55, left: 20 };

        options.legend.enabled = false;
        options.seriesDefaults.label.enabled = true;
        options.seriesDefaults.callout.length = 20;
    }

    return options;
}

function createRowData() {
    var countries = ["Ireland", "Spain", "United Kingdom", "France", "Germany", "Luxembourg", "Sweden",
        "Norway", "Italy", "Greece", "Iceland", "Portugal", "Malta", "Brazil", "Argentina",
        "Colombia", "Peru", "Venezuela", "Uruguay", "Belgium"];

    return countries.map(function(country, index) {
        return {
            country: country,
            gold: Math.floor(((index + 1 / 7) * 333) % 100),
            silver: Math.floor(((index + 1 / 3) * 555) % 100),
            bronze: Math.floor(((index + 1 / 7.3) * 777) % 100),
        };
    });
}

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);
});
<commit_msg>AG-2821 - added theme based configuration to custom toolbar example<commit_after>var columnDefs = [
    { field: 'country', width: 150, chartDataType: 'category' },
    { field: 'gold', chartDataType: 'series' },
    { field: 'silver', chartDataType: 'series' },
    { field: 'bronze', chartDataType: 'series' },
    {
        headerName: 'A',
        valueGetter: 'Math.floor(Math.random()*1000)',
        chartDataType: 'series',
    },
    {
        headerName: 'B',
        valueGetter: 'Math.floor(Math.random()*1000)',
        chartDataType: 'series',
    },
    {
        headerName: 'C',
        valueGetter: 'Math.floor(Math.random()*1000)',
        chartDataType: 'series',
    },
    {
        headerName: 'D',
        valueGetter: 'Math.floor(Math.random()*1000)',
        chartDataType: 'series',
    },
];

var gridOptions = {
    defaultColDef: {
        editable: true,
        sortable: true,
        flex: 1,
        minWidth: 100,
        filter: true,
        resizable: true,
    },
    columnDefs: columnDefs,
    rowData: createRowData(),
    popupParent: document.body,
    enableRangeSelection: true,
    onFirstDataRendered: onFirstDataRendered,
    enableCharts: true,
    getChartToolbarItems: getChartToolbarItems,
    chartThemeOverrides: {
        defaults: {
            pie: {
                title: {
                    enabled: true,
                    text: 'Precious Metals Production',
                    fontWeight: 'bold',
                    fontSize: 20,
                    color: 'rgb(100, 100, 100)',
                },
                subtitle: {
                    enabled: true,
                    text: 'by country',
                    fontStyle: 'italic',
                    fontWeight: 'bold',
                    fontSize: 14,
                    color: 'rgb(100, 100, 100)',
                },
                padding: {
                    top: 25,
                    right: 20,
                    bottom: 55,
                    left: 20
                },
                legend: {
                    enabled: false,
                },
                series: {
                    label: {
                        enabled: true,
                        callout: {
                            length: 900 //FIXME
                        }
                    }
                }
            }
        }
    },
};

function getChartToolbarItems() {
    return ['chartDownload', 'chartData', 'chartSettings'];
}

function onFirstDataRendered(params) {
    var createRangeChartParams = {
        cellRange: {
            rowStartIndex: 0,
            rowEndIndex: 4,
            columns: ['country', 'gold'],
        },
        chartType: 'pie',
    };

    params.api.createRangeChart(createRangeChartParams);
}

function createRowData() {
    var countries = [
        'Ireland',
        'Spain',
        'United Kingdom',
        'France',
        'Germany',
        'Luxembourg',
        'Sweden',
        'Norway',
        'Italy',
        'Greece',
        'Iceland',
        'Portugal',
        'Malta',
        'Brazil',
        'Argentina',
        'Colombia',
        'Peru',
        'Venezuela',
        'Uruguay',
        'Belgium',
    ];

    return countries.map(function (country, index) {
        return {
            country: country,
            gold: Math.floor(((index + 1 / 7) * 333) % 100),
            silver: Math.floor(((index + 1 / 3) * 555) % 100),
            bronze: Math.floor(((index + 1 / 7.3) * 777) % 100),
        };
    });
}

// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function () {
    var gridDiv = document.querySelector('#myGrid');
    new agGrid.Grid(gridDiv, gridOptions);
});
<|endoftext|>


<commit_before>'use strict';

const View = require('@scola/view');

class PopOutView extends View.Abstract {
  constructor() {
    super();

    this.isFullScreen = null;
    this.directions = [];

    this.options({
      above: {
        height: '24em',
        width: '24em'
      },
      below: {
        height: '100%',
        width: '100%'
      },
      threshold: '25em'
    });
  }

  build() {
    this.element('outer', 'div')
      .properties({
        className: 'scola out'
      })
      .style({
        background: 'rgba(0, 0, 0, 0.5)',
        bottom: 0,
        left: 0,
        opacity: 0,
        position: 'fixed',
        right: 0,
        top: 0
      })
      .animate({
        opacity: 1
      });

    this.element('wrapper', 'div')
      .properties({
        className: 'scola wrapper'
      })
      .style({
        position: 'absolute'
      })
      .appendTo(this.element('outer'));

    this.element('inner', 'div')
      .properties({
        className: 'scola inner'
      })
      .style({
        height: '100%',
        overflow: 'hidden',
        position: 'absolute',
        transform: 'scale(1)',
        width: '100%'
      })
      .listen({
        click: this.handleClick
      }, this)
      .appendTo(this.element('wrapper'));

    this
      .element('triangle', 'div')
      .properties({
        className: 'scola triangle'
      })
      .style({
        borderColor: 'transparent',
        borderStyle: 'solid',
        borderWidth: '0.75em',
        height: 0,
        position: 'absolute',
        width: 0,
        zIndex: 2
      })
      .appendTo(this.element('wrapper'));

    this.view(null, '@scola.pop.container').append(this);
    this.addHandlers();
  }

  setDimensions() {
    const threshold = this.getOption('threshold');

    this.element('wrapper')
      .match('not all and (min-width: ' + threshold + ')')
      .style(() => {
        return this
          .fullScreen(true)
          .getOption('below');
      })
      .match('(min-width: ' + threshold + ')')
      .style(() => {
        return this
          .fullScreen(false)
          .getOption('above');
      });
  }

  render() {
    return this.play().element('outer');
  }

  destroy() {
    this
      .element('outer')
      .animate({
        opacity: 0,
        play: true,
        onComplete: () => {
          this.removeHandlers();
          this.view(null, '@scola.pop.container').remove(this);
          super.destroy();
        }
      });
  }

  addHandlers() {
    this.bindListener('resize', this.window, this.debounce, this.rerender, 250);
  }

  removeHandlers() {
    this.unbindListener('resize', this.window, this.debounce);
  }

  handleClick(element, event) {
    event.stopPropagation();
  }

  anchor(element) {
    this.anchorElement = element;
    this.setDimensions();

    return this;
  }

  inside(element) {
    this.insideElement = element;
    return this;
  }

  left() {
    this.directions.push('left');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.leftInside();
    } else {
      this.leftAnchor();
    }

    if (this.directions.length === 1) {
      this.leftTriangleVertical();
    } else {
      this.leftTriangleHorizontal();
    }

    return this;
  }

  leftInside() {
    const position = this.insideElement.getPosition();

    this.element('wrapper')
      .style({
        left: position.x
      });

    return this;
  }

  leftAnchor() {
    const position = this.anchorElement.getPosition();
    const dimensions = this.anchorElement.getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        left: position.x
      })
      .if(this.directions.length === 1)
      .style({
        left: position.x + dimensions.width
      });

    return this;
  }

  leftTriangleHorizontal() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          innerPosition.x
      });
  }

  leftTriangleVertical() {
    this.element('triangle')
      .style({
        borderRightColor: '#FAFAFA',
        borderLeftWidth: 0,
        marginLeft: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginLeft: '1em'
      });
  }

  right() {
    this.directions.push('right');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.rightInside();
    } else {
      this.rightAnchor();
    }

    if (this.directions.length === 1) {
      this.rightTriangleVertical();
    } else {
      this.rightTriangleHorizontal();
    }

    return this;
  }

  rightInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: insidePosition.x +
          insideDimensions.width -
          innerDimensions.width
      });

    return this;
  }

  rightAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        left: anchorPosition.x +
          anchorDimensions.width -
          innerDimensions.width
      })
      .if(this.directions.length === 1)
      .style({
        left: anchorPosition.x -
          innerDimensions.width
      });

    return this;
  }

  rightTriangleHorizontal() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          innerPosition.x
      });
  }

  rightTriangleVertical() {
    this.element('triangle')
      .style({
        right: 0,
        borderLeftColor: '#FAFAFA',
        borderRightWidth: 0,
        marginRight: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginLeft: '-1em'
      });
  }

  center() {
    this.directions.push('center');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.centerInside();
    } else {
      this.centerAnchor();
    }

    if (this.directions.length === 2) {
      this.centerTriangleHorizontal();
    }

    return this;
  }

  centerInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: insidePosition.x +
          (insideDimensions.width / 2) -
          (innerDimensions.width / 2)
      });

    return this;
  }

  centerAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          (innerDimensions.width / 2)
      });

    return this;
  }

  centerTriangleHorizontal() {
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: innerDimensions.width / 2
      });
  }

  top() {
    this.directions.push('top');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.topInside();
    } else {
      this.topAnchor();
    }

    if (this.directions.length === 1) {
      this.topTriangleHorizontal();
    } else {
      this.topTriangleVertical();
    }

    return this;
  }

  topInside() {
    const position = this.insideElement.getPosition();

    this.element('wrapper')
      .style({
        top: position.y
      });

    return this;
  }

  topAnchor() {
    const position = this.anchorElement.getPosition();
    const dimensions = this.anchorElement.getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        top: position.y
      })
      .if(this.directions.length === 1)
      .style({
        top: position.y + dimensions.height
      });

    return this;
  }

  topTriangleHorizontal() {
    this.element('triangle')
      .style({
        borderBottomColor: '#FAFAFA',
        borderTopWidth: 0,
        marginTop: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginTop: '1em'
      });
  }

  topTriangleVertical() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          innerPosition.y
      });
  }

  bottom() {
    this.directions.push('bottom');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.bottomInside();
    } else {
      this.bottomAnchor();
    }

    if (this.directions.length === 1) {
      this.bottomTriangleHorizontal();
    } else {
      this.bottomTriangleVertical();
    }

    return this;
  }

  bottomInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: insidePosition.y +
          insideDimensions.height -
          innerDimensions.height
      });

    return this;
  }

  bottomAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        top: anchorPosition.y +
          anchorDimensions.height -
          innerDimensions.height
      })
      .if(this.directions.length === 1)
      .style({
        top: anchorPosition.y -
          innerDimensions.height
      });

    return this;
  }

  bottomTriangleHorizontal() {
    this.element('triangle')
      .style({
        bottom: 0,
        borderTopColor: '#FAFAFA',
        borderBottomWidth: 0,
        marginBottom: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginTop: '-1em'
      });
  }

  bottomTriangleVertical() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          innerPosition.y
      });
  }

  middle() {
    this.directions.push('middle');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.middleInside();
    } else {
      this.middleAnchor();
    }

    if (this.directions.length === 2) {
      this.middleTriangleVertical();
    }

    return this;
  }

  middleInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: insidePosition.y +
          (insideDimensions.height / 2) -
          (innerDimensions.height / 2)
      });

    return this;
  }

  middleAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          (innerDimensions.height / 2)
      });

    return this;
  }

  middleTriangleVertical() {
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: innerDimensions.height / 2
      });
  }

  fullScreen(fullScreen) {
    this.isFullScreen = fullScreen;

    this.element('wrapper')
      .if(fullScreen)
      .style({
        left: 0,
        marginLeft: null,
        marginTop: null,
        top: null
      });

    this.element('inner')
      .if(fullScreen)
      .style({
        borderRadius: 0,
        overflow: 'initial'
      })
      .if(!fullScreen)
      .style({
        borderRadius: '1em',
        overflow: 'hidden'
      });

    this.element('triangle')
      .if(fullScreen)
      .style({
        display: 'none'
      })
      .if(!fullScreen)
      .style({
        display: 'block'
      });

    return this;
  }

  rerender() {
    const directions = this.directions;
    this.directions = [];

    directions.forEach((direction) => {
      switch (direction) {
        case 'left':
          this.left();
          break;
        case 'right':
          this.right();
          break;
        case 'center':
          this.center();
          break;
        case 'top':
          this.top();
          break;
        case 'bottom':
          this.bottom();
          break;
        case 'middle':
          this.middle();
          break;
      }
    });
  }
}

module.exports = PopOutView;
<commit_msg>Remove obsolete overflow style<commit_after>'use strict';

const View = require('@scola/view');

class PopOutView extends View.Abstract {
  constructor() {
    super();

    this.isFullScreen = null;
    this.directions = [];

    this.options({
      above: {
        height: '24em',
        width: '24em'
      },
      below: {
        height: '100%',
        width: '100%'
      },
      threshold: '25em'
    });
  }

  build() {
    this.element('outer', 'div')
      .properties({
        className: 'scola out'
      })
      .style({
        background: 'rgba(0, 0, 0, 0.5)',
        bottom: 0,
        left: 0,
        opacity: 0,
        position: 'fixed',
        right: 0,
        top: 0
      })
      .animate({
        opacity: 1
      });

    this.element('wrapper', 'div')
      .properties({
        className: 'scola wrapper'
      })
      .style({
        position: 'absolute'
      })
      .appendTo(this.element('outer'));

    this.element('inner', 'div')
      .properties({
        className: 'scola inner'
      })
      .style({
        height: '100%',
        overflow: 'hidden',
        position: 'absolute',
        transform: 'scale(1)',
        width: '100%'
      })
      .listen({
        click: this.handleClick
      }, this)
      .appendTo(this.element('wrapper'));

    this
      .element('triangle', 'div')
      .properties({
        className: 'scola triangle'
      })
      .style({
        borderColor: 'transparent',
        borderStyle: 'solid',
        borderWidth: '0.75em',
        height: 0,
        position: 'absolute',
        width: 0,
        zIndex: 2
      })
      .appendTo(this.element('wrapper'));

    this.view(null, '@scola.pop.container').append(this);
    this.addHandlers();
  }

  setDimensions() {
    const threshold = this.getOption('threshold');

    this.element('wrapper')
      .match('not all and (min-width: ' + threshold + ')')
      .style(() => {
        return this
          .fullScreen(true)
          .getOption('below');
      })
      .match('(min-width: ' + threshold + ')')
      .style(() => {
        return this
          .fullScreen(false)
          .getOption('above');
      });
  }

  render() {
    return this.play().element('outer');
  }

  destroy() {
    this
      .element('outer')
      .animate({
        opacity: 0,
        play: true,
        onComplete: () => {
          this.removeHandlers();
          this.view(null, '@scola.pop.container').remove(this);
          super.destroy();
        }
      });
  }

  addHandlers() {
    this.bindListener('resize', this.window, this.debounce, this.rerender, 250);
  }

  removeHandlers() {
    this.unbindListener('resize', this.window, this.debounce);
  }

  handleClick(element, event) {
    event.stopPropagation();
  }

  anchor(element) {
    this.anchorElement = element;
    this.setDimensions();

    return this;
  }

  inside(element) {
    this.insideElement = element;
    return this;
  }

  left() {
    this.directions.push('left');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.leftInside();
    } else {
      this.leftAnchor();
    }

    if (this.directions.length === 1) {
      this.leftTriangleVertical();
    } else {
      this.leftTriangleHorizontal();
    }

    return this;
  }

  leftInside() {
    const position = this.insideElement.getPosition();

    this.element('wrapper')
      .style({
        left: position.x
      });

    return this;
  }

  leftAnchor() {
    const position = this.anchorElement.getPosition();
    const dimensions = this.anchorElement.getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        left: position.x
      })
      .if(this.directions.length === 1)
      .style({
        left: position.x + dimensions.width
      });

    return this;
  }

  leftTriangleHorizontal() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          innerPosition.x
      });
  }

  leftTriangleVertical() {
    this.element('triangle')
      .style({
        borderRightColor: '#FAFAFA',
        borderLeftWidth: 0,
        marginLeft: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginLeft: '1em'
      });
  }

  right() {
    this.directions.push('right');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.rightInside();
    } else {
      this.rightAnchor();
    }

    if (this.directions.length === 1) {
      this.rightTriangleVertical();
    } else {
      this.rightTriangleHorizontal();
    }

    return this;
  }

  rightInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: insidePosition.x +
          insideDimensions.width -
          innerDimensions.width
      });

    return this;
  }

  rightAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        left: anchorPosition.x +
          anchorDimensions.width -
          innerDimensions.width
      })
      .if(this.directions.length === 1)
      .style({
        left: anchorPosition.x -
          innerDimensions.width
      });

    return this;
  }

  rightTriangleHorizontal() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          innerPosition.x
      });
  }

  rightTriangleVertical() {
    this.element('triangle')
      .style({
        right: 0,
        borderLeftColor: '#FAFAFA',
        borderRightWidth: 0,
        marginRight: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginLeft: '-1em'
      });
  }

  center() {
    this.directions.push('center');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.centerInside();
    } else {
      this.centerAnchor();
    }

    if (this.directions.length === 2) {
      this.centerTriangleHorizontal();
    }

    return this;
  }

  centerInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: insidePosition.x +
          (insideDimensions.width / 2) -
          (innerDimensions.width / 2)
      });

    return this;
  }

  centerAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        left: anchorPosition.x +
          (anchorDimensions.width / 2) -
          (innerDimensions.width / 2)
      });

    return this;
  }

  centerTriangleHorizontal() {
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('triangle')
      .style({
        marginLeft: '-0.75em',
        left: innerDimensions.width / 2
      });
  }

  top() {
    this.directions.push('top');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.topInside();
    } else {
      this.topAnchor();
    }

    if (this.directions.length === 1) {
      this.topTriangleHorizontal();
    } else {
      this.topTriangleVertical();
    }

    return this;
  }

  topInside() {
    const position = this.insideElement.getPosition();

    this.element('wrapper')
      .style({
        top: position.y
      });

    return this;
  }

  topAnchor() {
    const position = this.anchorElement.getPosition();
    const dimensions = this.anchorElement.getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        top: position.y
      })
      .if(this.directions.length === 1)
      .style({
        top: position.y + dimensions.height
      });

    return this;
  }

  topTriangleHorizontal() {
    this.element('triangle')
      .style({
        borderBottomColor: '#FAFAFA',
        borderTopWidth: 0,
        marginTop: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginTop: '1em'
      });
  }

  topTriangleVertical() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          innerPosition.y
      });
  }

  bottom() {
    this.directions.push('bottom');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.bottomInside();
    } else {
      this.bottomAnchor();
    }

    if (this.directions.length === 1) {
      this.bottomTriangleHorizontal();
    } else {
      this.bottomTriangleVertical();
    }

    return this;
  }

  bottomInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: insidePosition.y +
          insideDimensions.height -
          innerDimensions.height
      });

    return this;
  }

  bottomAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .if(this.directions.length === 2)
      .style({
        top: anchorPosition.y +
          anchorDimensions.height -
          innerDimensions.height
      })
      .if(this.directions.length === 1)
      .style({
        top: anchorPosition.y -
          innerDimensions.height
      });

    return this;
  }

  bottomTriangleHorizontal() {
    this.element('triangle')
      .style({
        bottom: 0,
        borderTopColor: '#FAFAFA',
        borderBottomWidth: 0,
        marginBottom: '-0.75em'
      });

    this.element('wrapper')
      .style({
        marginTop: '-1em'
      });
  }

  bottomTriangleVertical() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerPosition = this.element('wrapper').getPosition();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          innerPosition.y
      });
  }

  middle() {
    this.directions.push('middle');

    if (this.isFullScreen) {
      return this;
    }

    if (this.insideElement) {
      this.middleInside();
    } else {
      this.middleAnchor();
    }

    if (this.directions.length === 2) {
      this.middleTriangleVertical();
    }

    return this;
  }

  middleInside() {
    const insidePosition = this.insideElement.getPosition();
    const insideDimensions = this.insideElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: insidePosition.y +
          (insideDimensions.height / 2) -
          (innerDimensions.height / 2)
      });

    return this;
  }

  middleAnchor() {
    const anchorPosition = this.anchorElement.getPosition();
    const anchorDimensions = this.anchorElement.getDimensions();
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('wrapper')
      .style({
        top: anchorPosition.y +
          (anchorDimensions.height / 2) -
          (innerDimensions.height / 2)
      });

    return this;
  }

  middleTriangleVertical() {
    const innerDimensions = this.element('wrapper').getDimensions();

    this.element('triangle')
      .style({
        marginTop: '-0.75em',
        top: innerDimensions.height / 2
      });
  }

  fullScreen(fullScreen) {
    this.isFullScreen = fullScreen;

    this.element('wrapper')
      .if(fullScreen)
      .style({
        left: 0,
        marginLeft: null,
        marginTop: null,
        top: null
      });

    this.element('inner')
      .if(fullScreen)
      .style({
        borderRadius: 0
      })
      .if(!fullScreen)
      .style({
        borderRadius: '1em'
      });

    this.element('triangle')
      .if(fullScreen)
      .style({
        display: 'none'
      })
      .if(!fullScreen)
      .style({
        display: 'block'
      });

    return this;
  }

  rerender() {
    const directions = this.directions;
    this.directions = [];

    directions.forEach((direction) => {
      switch (direction) {
        case 'left':
          this.left();
          break;
        case 'right':
          this.right();
          break;
        case 'center':
          this.center();
          break;
        case 'top':
          this.top();
          break;
        case 'bottom':
          this.bottom();
          break;
        case 'middle':
          this.middle();
          break;
      }
    });
  }
}

module.exports = PopOutView;
<|endoftext|>


<commit_before>/*
 * grunt-gitinfo
 * https://github.com/damkraw/grunt-gitinfo
 *
 * Copyright (c) 2013 Damian Krawczyk
 * Licensed under the MIT license.
 */

'use strict';

module.exports = function(grunt) {
    grunt.registerTask('gitinfo', 'Your task description goes here.', function () {
        var done = this.async(),
        gitinfo = {},
        commands = {
            'local.branch.current.name'     : ['rev-parse', '--abbrev-ref', 'HEAD'],
            'local.branch.current.SHA'      : ['rev-parse', 'HEAD'],
            'local.branch.current.shortSHA' : ['rev-parse', '--short', 'HEAD'],
            'remote.origin.url'             : ['config', '--get-all', 'remote.origin.url']
        };

        function work(conf_key, cb) {
            var spawn_args = commands[conf_key];

            grunt.util.spawn(
                {
                    cmd  : 'git',
                    args : spawn_args
                },
                function (err, result) {
                    if (err) {
                        console.warn("[gitinfo]: couldn't set config:", conf_key);
                    } else {
                        var ref = gitinfo, keys = conf_key.split(".");
                        for (var i = 0; i < keys.length-1; i++) {
                            var key = keys[i];

                            if (ref[key] === undefined) {
                                ref[key] = {};
                            }

                            ref = ref[key];
                        }

                        ref[keys.pop()] = result.stdout;

                        if (grunt.option("debug") || grunt.option("verbose")) {
                            console.log("[gitinfo]:", conf_key, "=", result.stdout);
                        }
                    }

                    cb();
            });
        }

        function fin() {
            grunt.config.set('gitinfo', gitinfo);
            done();
        }

        grunt.util.async.forEach(grunt.util._.keys(commands), work, fin);
    });
};<commit_msg>c2h5oh changes: - last commit author - last commit time - commit tag - username - cwd<commit_after>/*
 * grunt-gitinfo
 * https://github.com/damkraw/grunt-gitinfo
 *
 * Copyright (c) 2013 Damian Krawczyk, Maciej Lisiewski
 * Licensed under the MIT license.
 */

// JSLint
/*global module, console*/

module.exports = function (grunt) {
    'use strict';
    grunt.registerTask('gitinfo', 'Your task description goes here.', function () {
        var done = this.async(),
            gitinfo = {},
            config = grunt.config.get('gitinfo'),
            commands = {
                'local.branch.current.name'             : ['rev-parse', '--abbrev-ref', 'HEAD'],
                'local.branch.current.SHA'              : ['rev-parse', 'HEAD'],
                'local.branch.current.shortSHA'         : ['rev-parse', '--short', 'HEAD'],
                'local.branch.current.currentUser'      : ['config', '--global', 'user.name'],
                'local.branch.current.lastCommitTime'   : ['log', '--format="%ai"', '-n1', 'HEAD'],
                'local.branch.current.lastCommitAuthor' : ['log', '--format="%aN"', '-n1', 'HEAD'],
                'local.branch.current.tag'              : ['describe', '--abbrev=0', '--exact-match'],
                'remote.origin.url'                     : ['config', '--get-all', 'remote.origin.url']
            },

            work = function (conf_key, cb) {
                var spawn_args = commands[conf_key];

                grunt.util.spawn(
                    {
                        cmd  : 'git',
                        args : spawn_args,
                        opts : {
                            cwd : (config.options && config.options.cwd) ? config.options.cwd : null
                        }
                    },
                    function (err, result) {
                        if (err) {
                            console.warn("[gitinfo]: couldn't set config:", conf_key);
                        } else {
                            var ref = gitinfo, keys = conf_key.split("."), i, key;
                            for (i = 0; i < keys.length - 1; i += 1) {
                                key = keys[i];

                                if (ref[key] === undefined) {
                                    ref[key] = {};
                                }

                                ref = ref[key];
                            }

                            ref[keys.pop()] = result.stdout;

                            if (grunt.option("debug") || grunt.option("verbose")) {
                                console.log("[gitinfo]:", conf_key, "=", result.stdout);
                            }
                        }
                        cb();
                    }
                );
            },

            fin = function () {
                grunt.config.set('gitinfo', gitinfo);
                done();
            };

        grunt.util.async.forEach(grunt.util._.keys(commands), work, fin);
    });
};<|endoftext|>


<commit_before>window.onload = function() {
    const { ipcRenderer, webFrame, shell, remote, clipboard } = require('electron');
    const GmailApi = require('node-gmail-new');
    const jquery = require('jquery');
    const page = require('./gmail');
    const config = require("./config");
    const { extractDate, addToCalendar } = require('./calendar');

    // window.__devtron = {require: require, process: process}
    window.j = jquery;
    window.page = new page();
    window.Gmail = GmailApi(jquery);
    window.notified = [];
    window.webFrame = webFrame;
    window.address = "";
    window.calendar = [];
    window.set_of_emails = new Set();
    window.email_ids_to_notifications = {};

    // Override alert function
    (function(proxied) {
        window.alert = function() {
            if (!arguments[0].match('Grrr')) {
                return proxied.apply(this, arguments);
            }
        };
    })(window.alert);

    let parseGmailFeed = (text) => {
        let current_unread_email_ids = [];

        var oParser = new DOMParser();
        var oDOM = oParser.parseFromString(text, "text/xml");

        ipcRenderer.send('update-dock', oDOM.querySelectorAll('entry').length);

        oDOM.querySelectorAll('entry').forEach( entry => {
            let id = entry.querySelector('id').innerHTML;
            current_unread_email_ids.push(id);
            if (!(window.set_of_emails.has(id))) {
                window.set_of_emails.add(id);
                let from = entry.querySelector('author').querySelector('name').innerHTML;
                let title = entry.querySelector('title').innerHTML;
                let link = entry.querySelector('link').getAttribute('href');
                console.info(`New email: ${title}`);
                let notification = new Notification(from, {body: title, data: link});
                notification.addEventListener('click', (event) => {
                    location.href = event.target.data;
                })
                window.email_ids_to_notifications[id] = notification;
            }
        })
        window.set_of_emails.forEach( (id) => {
            if (!current_unread_email_ids.includes(id)) {
                window.email_ids_to_notifications[id].close();
            }
        });
    }

    function startRefresh(){
        const feed_url = "https://mail.google.com/mail/feed/atom";
        fetch(feed_url, {credentials: 'include'})
        .then( response => response.text() )
        .then( responseText => parseGmailFeed(responseText) )
        .catch( error => { console.log("An error occurred in fetch."); } )
        let interval = 5000 + 500 * Math.random();
        setTimeout(startRefresh, interval);
    }

    startRefresh();

    ipcRenderer.on('start-compose', (event, address) => {
        window.address = address;
        window.Gmail.compose.start_compose();
    });
    ipcRenderer.on('logout', window.page.logout.bind(window.page));
    ipcRenderer.on('navigate', (event, place) => {
        window.page.navigateTo(place);
    });
    ipcRenderer.on('zoom', (event, factor) => {
        webFrame.setZoomFactor(factor);
    });
    ipcRenderer.on('close-calendar', (event) => {
        if (window.calendar) {
            window.calendar[0].close();
            window.calendar = [];
        }
    });

    window.Gmail.observe.on("compose", function(compose, type) {
        setTimeout(function(compose) {
            if (window.address) {
                compose.$el[0].querySelector("[name=to]").innerHTML = window.address;
            }
        }, 50, compose);
        setTimeout(function() {
            window.address = "";
        }, 500);
    });

    window.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        if (e.target.closest('textarea, input, [contenteditable="true"]')) {
            const buildEditorContextMenu = remote.require('electron-editor-context-menu');
            let menu = buildEditorContextMenu();
            setTimeout(() => {
                menu.popup(remote.getCurrentWindow());
            }, 30);
        }
        else {
            if (!window.getSelection().isCollapsed) {
                console.log(window.getSelection());
                const Menu = remote.Menu;
                const MenuItem = remote.MenuItem;
                const menu = new Menu();
                menu.append(new MenuItem({ label: 'Copy Text', role: "copy" }));
                if (window.getSelection().focusNode instanceof HTMLElement && window.getSelection().focusNode.closest("a") != null){
                    url = window.getSelection().focusNode.closest("a").getAttribute("href");
                    menu.append(new MenuItem({ label: 'Copy URL', click: () => {
                        clipboard.writeText(url);
                    } }));
                }
                else if (window.getSelection().focusNode.parentElement instanceof HTMLElement && window.getSelection().focusNode.parentElement.closest("a") != null) {
                    url = window.getSelection().focusNode.parentElement.closest("a").getAttribute("href");
                    menu.append(new MenuItem({ label: 'Copy URL', click: () => {
                        clipboard.writeText(url);
                    } }));
                }
                menu.append(new MenuItem({ label: 'Search in Google', click: () => {
                    let text = window.getSelection().toString();
                    shell.openExternal("https://google.com/search?q="+text);
                }}));
                let date = extractDate(window.getSelection().toString());
                if (date) {
                    console.info(date);
                    menu.append(new MenuItem({ label: 'Add to Calendar', click: () => {
                        addToCalendar(date);
                    } }));
                }
                setTimeout(function() {
                    menu.popup(remote.getCurrentWindow());
                }, 30);
            }
        }
    });
};

<commit_msg>Fix click handler for notifcations<commit_after>window.onload = function() {
    const { ipcRenderer, webFrame, shell, remote, clipboard } = require('electron');
    const GmailApi = require('node-gmail-new');
    const jquery = require('jquery');
    const page = require('./gmail');
    const config = require("./config");
    const { extractDate, addToCalendar } = require('./calendar');

    // window.__devtron = {require: require, process: process}
    window.j = jquery;
    window.page = new page();
    window.Gmail = GmailApi(jquery);
    window.notified = [];
    window.webFrame = webFrame;
    window.address = "";
    window.calendar = [];
    window.set_of_emails = new Set();
    window.email_ids_to_notifications = {};

    // Override alert function
    (function(proxied) {
        window.alert = function() {
            if (!arguments[0].match('Grrr')) {
                return proxied.apply(this, arguments);
            }
        };
    })(window.alert);

    let parseGmailFeed = (text) => {
        let current_unread_email_ids = [];

        var oParser = new DOMParser();
        var oDOM = oParser.parseFromString(text, "text/xml");

        ipcRenderer.send('update-dock', oDOM.querySelectorAll('entry').length);

        oDOM.querySelectorAll('entry').forEach( entry => {
            let id = entry.querySelector('id').innerHTML;
            current_unread_email_ids.push(id);
            if (!(window.set_of_emails.has(id))) {
                window.set_of_emails.add(id);
                let from = entry.querySelector('author').querySelector('name').innerHTML;
                let title = entry.querySelector('title').innerHTML;
                let link = entry.querySelector('link').getAttribute('href');
                let oid = link.match(/message_id=(\w+)/)[1]
                console.info(`New email: ${title}`);
                let notification = new Notification(from, {body: title, data: oid});
                notification.addEventListener('click', (event) => {
                    let oid = event.target.data;
                    location.href = location.href.replace(/#inbox.*/, `#inbox/${oid}`);
                })
                window.email_ids_to_notifications[id] = notification;
            }
        })
        window.set_of_emails.forEach( (id) => {
            if (!current_unread_email_ids.includes(id)) {
                window.email_ids_to_notifications[id].close();
            }
        });
    }

    function startRefresh(){
        const feed_url = "https://mail.google.com/mail/feed/atom";
        fetch(feed_url, {credentials: 'include'})
        .then( response => response.text() )
        .then( responseText => parseGmailFeed(responseText) )
        .catch( error => { console.log("An error occurred in fetch."); } )
        let interval = 5000 + 500 * Math.random();
        setTimeout(startRefresh, interval);
    }

    startRefresh();

    ipcRenderer.on('start-compose', (event, address) => {
        window.address = address;
        window.Gmail.compose.start_compose();
    });
    ipcRenderer.on('logout', window.page.logout.bind(window.page));
    ipcRenderer.on('navigate', (event, place) => {
        window.page.navigateTo(place);
    });
    ipcRenderer.on('zoom', (event, factor) => {
        webFrame.setZoomFactor(factor);
    });
    ipcRenderer.on('close-calendar', (event) => {
        if (window.calendar) {
            window.calendar[0].close();
            window.calendar = [];
        }
    });

    window.Gmail.observe.on("compose", function(compose, type) {
        setTimeout(function(compose) {
            if (window.address) {
                compose.$el[0].querySelector("[name=to]").innerHTML = window.address;
            }
        }, 50, compose);
        setTimeout(function() {
            window.address = "";
        }, 500);
    });

    window.addEventListener('contextmenu', (e) => {
        e.preventDefault();
        if (e.target.closest('textarea, input, [contenteditable="true"]')) {
            const buildEditorContextMenu = remote.require('electron-editor-context-menu');
            let menu = buildEditorContextMenu();
            setTimeout(() => {
                menu.popup(remote.getCurrentWindow());
            }, 30);
        }
        else {
            if (!window.getSelection().isCollapsed) {
                console.log(window.getSelection());
                const Menu = remote.Menu;
                const MenuItem = remote.MenuItem;
                const menu = new Menu();
                menu.append(new MenuItem({ label: 'Copy Text', role: "copy" }));
                if (window.getSelection().focusNode instanceof HTMLElement && window.getSelection().focusNode.closest("a") != null){
                    url = window.getSelection().focusNode.closest("a").getAttribute("href");
                    menu.append(new MenuItem({ label: 'Copy URL', click: () => {
                        clipboard.writeText(url);
                    } }));
                }
                else if (window.getSelection().focusNode.parentElement instanceof HTMLElement && window.getSelection().focusNode.parentElement.closest("a") != null) {
                    url = window.getSelection().focusNode.parentElement.closest("a").getAttribute("href");
                    menu.append(new MenuItem({ label: 'Copy URL', click: () => {
                        clipboard.writeText(url);
                    } }));
                }
                menu.append(new MenuItem({ label: 'Search in Google', click: () => {
                    let text = window.getSelection().toString();
                    shell.openExternal("https://google.com/search?q="+text);
                }}));
                let date = extractDate(window.getSelection().toString());
                if (date) {
                    console.info(date);
                    menu.append(new MenuItem({ label: 'Add to Calendar', click: () => {
                        addToCalendar(date);
                    } }));
                }
                setTimeout(function() {
                    menu.popup(remote.getCurrentWindow());
                }, 30);
            }
        }
    });
};

<|endoftext|>


<commit_before>/**
 * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/volojs/grunt-volo for details
 */

/*jslint node: true */
'use strict';

console.log('LOADING VOLO');

module.exports = function (grunt) {
    grunt.registerTask('volo', 'Use volo to fetch code from GitHub', function () {
        var volo = require('volo'),
            args = this.args,
            //Tell grunt this is an async task.
            done = this.async();

        volo(args).then(function (okText) {
            if (okText) {
                grunt.log.ok(okText);
                done(true);
            }
        }, function (errText) {
            grunt.log.error('ERROR: ' + errText);
            done(false);
        });
    });
};
<commit_msg>Remove console.log call on load<commit_after>/**
 * @license Copyright (c) 2012, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/volojs/grunt-volo for details
 */

/*jslint node: true */
'use strict';

module.exports = function (grunt) {
    grunt.registerTask('volo', 'Use volo to fetch code from GitHub', function () {
        var volo = require('volo'),
            args = this.args,
            //Tell grunt this is an async task.
            done = this.async();

        volo(args).then(function (okText) {
            if (okText) {
                grunt.log.ok(okText);
                done(true);
            }
        }, function (errText) {
            grunt.log.error('ERROR: ' + errText);
            done(false);
        });
    });
};
<|endoftext|>


<commit_before>angular.module('momentum')
  .factory('Email', Email);

Email.$inject = ['$http', '$auth'];

function Email($http, $auth) {
    return {
		subscribe: subscribe
    };

    function subscribe(user) {
		return $http.post('/subscribe/', user);
	}
}<commit_msg>updated frontend routes for email service<commit_after>angular.module('momentum')
  .factory('Email', Email);

Email.$inject = ['$http', '$auth'];

function Email($http, $auth) {
    return {
		subscribe: subscribe
    };

    function subscribe(user) {
		return $http.post('/email/subscribe/', user);
	}
}<|endoftext|>