<commit_before>var fs = require('fs');
var vm = require('vm');
var net = require('net');
var child_process = require('child_process');
var Bacon = require('baconjs');
var SSE = require('express-sse');
var request = require('request');

var opt = require('node-getopt').create([
  ['h', 'help', 'display this help'],
  ['v', 'version', 'show version'],
  ['p', 'port=PORT', 'listen port']
])
.bindHelp()
.parseSystem();

if (opt.options.version) {
    console.log('nwatchlive 0.0.1');
    process.exit();
}

var port = opt.options.port || 3050;

if (opt.argv.length == 0) {
    console.log('no services specified.');
    process.exit(1);
}

var watchers = {};

var watchHTTP = function(url) {
    return function(ack, err) {
        request(url, function(e, response, body) {
            if (e) {
                err(e.message);
            } else if (response.statusCode != 200) {
                err("status " + response.statusCode);
            } else {
                ack();
            }
        });
    };
};

var watchTCP = function(host, port) {
    return function(ack, err) {
        var cte = false;
        var conn = net.createConnection({'host': host,
                                         'port': port},
                                        function() {
            ack();
            cte = true;
            conn.end();
        });
        conn.on('end', function() {
            if (!cte) {
                err('premature FIN');
            }
        });
        conn.on('timeout', function() {
            err('timeout');
        });
        conn.on('error', function(e) {
            err(e.message);
        });
    };
};

var watchChild = function(child, args) {
    return function(ack, err) {
        var chld = child_process.spawn(child, args);
        chld.on('error', function(e) {
            err(e.message);
        });
        chld.on('exit', function(code, signal) {
            if (signal !== null) {
                err(signal);
            } else if (code != 0) {
                err('Exited with code ' + code);
            } else {
                ack();
            }
        });
    };
};

var watchPing = function(target) {
    return watchChild('ping', ['-c', '1', '-W', '3', target]);
};

var watchPing6 = function(target) {
    return watchChild('ping6', ['-c', '1', '-W', '3', target]);
};

var context = vm.createContext({
    'addWatcher': function(name, watcher) {
        watchers[name] = watcher;
    },
    'watchHTTP': watchHTTP,
    'watchChild': watchChild,
    'watchTCP': watchTCP,
    'watchPing': watchPing,
    'watchPing6': watchPing6,
    'require': require,
    'console': console
});
opt.argv.forEach(function(sfile) {
    var services = fs.readFileSync(sfile);

    vm.runInContext(services, context, sfile);
});
console.log(watchers);

var services = [];
for (var watcher in watchers) {
    if (watchers.hasOwnProperty(watcher)) {
        services.push(watcher);
    }
}
var statuses = {};
services.forEach(function(service) {
    statuses[service] = '...';
});
var statBus = new Bacon.Bus();
var Stat = statBus.toProperty(statuses);

var setStatus = function(service, stat) {
    var oldStatus = statuses[service];
    if (oldStatus === stat) {
        return;
    }
    statuses[service] = stat;
    statBus.push(statuses);
};

var propertiesInflight = [];
var currentQueryGeneration = 0;

var runQueries = function() {
    currentQueryGeneration += 1;
    var currentQuery = currentQueryGeneration;
    propertiesInflight.forEach(function(inflight) {
        setStatus(inflight, 'query timed out');
    });
    services.forEach(function(service) {
        propertiesInflight.push(service);
        var watcher = watchers[service];
        var recv = function(stat) {
            if (currentQuery !== currentQueryGeneration)
                return;
            var ix = propertiesInflight.indexOf(service);
            if (ix > -1) {
                propertiesInflight.splice(ix, 1);
                setStatus(service, stat);
            }
        };
        var ack = function() {
            recv(null);
        };
        var err = function(e) {
            recv(e || 'error');
        };
        setImmediate(function() {
            watcher(ack, err);
        });
    });
};

runQueries();

var INTERVAL = 6;
setInterval(runQueries, INTERVAL*1000);

Stat.onValue(function(val) {
    console.log(val);
});

var express = require('express');
var app = express();
var root = fs.readFileSync(__dirname + '/index.html', {'encoding': 'utf-8'});
root = root.replace('$ROOT$', '');

app.get('/', function(req, res) {
    res.header('Content-Type', 'text/html; charset=utf-8');
    res.end(root);
});

app.get('/status', function(req, res) {
    res.header('Content-Type', 'application/json');
    res.end(JSON.stringify(statuses));
});

var sse = new SSE([]);

app.get('/stream', sse.init);

Stat.debounce(250).onValue(function(x) {
    sse.send(x);
    sse.updateInit([x]);
});

app.use('/static', express.static(__dirname + '/static'));

var server = app.listen(port, '::', function() {
    var ad = server.address();
    var hs = ad.address;
    var pt = ad.port;
    console.log("Listening on http://%s:%s", hs, pt);
});

<commit_msg>Include output in child failures<commit_after>var fs = require('fs');
var vm = require('vm');
var net = require('net');
var child_process = require('child_process');
var Bacon = require('baconjs');
var SSE = require('express-sse');
var request = require('request');

var opt = require('node-getopt').create([
  ['h', 'help', 'display this help'],
  ['v', 'version', 'show version'],
  ['p', 'port=PORT', 'listen port']
])
.bindHelp()
.parseSystem();

if (opt.options.version) {
    console.log('nwatchlive 0.0.1');
    process.exit();
}

var port = opt.options.port || 3050;

if (opt.argv.length == 0) {
    console.log('no services specified.');
    process.exit(1);
}

var watchers = {};

var watchHTTP = function(url) {
    return function(ack, err) {
        request(url, function(e, response, body) {
            if (e) {
                err(e.message);
            } else if (response.statusCode != 200) {
                err("status " + response.statusCode);
            } else {
                ack();
            }
        });
    };
};

var watchTCP = function(host, port) {
    return function(ack, err) {
        var cte = false;
        var conn = net.createConnection({'host': host,
                                         'port': port},
                                        function() {
            ack();
            cte = true;
            conn.end();
        });
        conn.on('end', function() {
            if (!cte) {
                err('premature FIN');
            }
        });
        conn.on('timeout', function() {
            err('timeout');
        });
        conn.on('error', function(e) {
            err(e.message);
        });
    };
};

var watchChild = function(child, args) {
    return function(ack, err) {
        var chld = child_process.spawn(child, args, {
            'stdio': ['ignore', 'pipe', 'pipe']
        });
        var io = '';
        var getIO = function(chunk) {
            io += chunk
        };
        chld.stdout.on('data', getIO);
        chld.stderr.on('data', getIO);
        chld.on('error', function(e) {
            err(e.message);
        });
        chld.on('exit', function(code, signal) {
            if (signal !== null || code != 0) {
                err(io);
            } else {
                ack();
            }
        });
    };
};

var watchPing = function(target) {
    return watchChild('ping', ['-c', '1', '-W', '3', target]);
};

var watchPing6 = function(target) {
    return watchChild('ping6', ['-c', '1', '-W', '3', target]);
};

var context = vm.createContext({
    'addWatcher': function(name, watcher) {
        watchers[name] = watcher;
    },
    'watchHTTP': watchHTTP,
    'watchChild': watchChild,
    'watchTCP': watchTCP,
    'watchPing': watchPing,
    'watchPing6': watchPing6,
    'require': require,
    'console': console
});
opt.argv.forEach(function(sfile) {
    var services = fs.readFileSync(sfile);

    vm.runInContext(services, context, sfile);
});
console.log(watchers);

var services = [];
for (var watcher in watchers) {
    if (watchers.hasOwnProperty(watcher)) {
        services.push(watcher);
    }
}
var statuses = {};
services.forEach(function(service) {
    statuses[service] = '...';
});
var statBus = new Bacon.Bus();
var Stat = statBus.toProperty(statuses);

var setStatus = function(service, stat) {
    var oldStatus = statuses[service];
    if (oldStatus === stat) {
        return;
    }
    statuses[service] = stat;
    statBus.push(statuses);
};

var propertiesInflight = [];
var currentQueryGeneration = 0;

var runQueries = function() {
    currentQueryGeneration += 1;
    var currentQuery = currentQueryGeneration;
    propertiesInflight.forEach(function(inflight) {
        setStatus(inflight, 'query timed out');
    });
    services.forEach(function(service) {
        propertiesInflight.push(service);
        var watcher = watchers[service];
        var recv = function(stat) {
            if (currentQuery !== currentQueryGeneration)
                return;
            var ix = propertiesInflight.indexOf(service);
            if (ix > -1) {
                propertiesInflight.splice(ix, 1);
                setStatus(service, stat);
            }
        };
        var ack = function() {
            recv(null);
        };
        var err = function(e) {
            recv(e || 'error');
        };
        setImmediate(function() {
            watcher(ack, err);
        });
    });
};

runQueries();

var INTERVAL = 6;
setInterval(runQueries, INTERVAL*1000);

Stat.onValue(function(val) {
    console.log(val);
});

var express = require('express');
var app = express();
var root = fs.readFileSync(__dirname + '/index.html', {'encoding': 'utf-8'});
root = root.replace('$ROOT$', '');

app.get('/', function(req, res) {
    res.header('Content-Type', 'text/html; charset=utf-8');
    res.end(root);
});

app.get('/status', function(req, res) {
    res.header('Content-Type', 'application/json');
    res.end(JSON.stringify(statuses));
});

var sse = new SSE([]);

app.get('/stream', sse.init);

Stat.debounce(250).onValue(function(x) {
    sse.send(x);
    sse.updateInit([x]);
});

app.use('/static', express.static(__dirname + '/static'));

var server = app.listen(port, '::', function() {
    var ad = server.address();
    var hs = ad.address;
    var pt = ad.port;
    console.log("Listening on http://%s:%s", hs, pt);
});

<|endoftext|>


<commit_before>/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, console*/
define(function (require, exports, module) {
    'use strict';

    var EditorManager       = brackets.getModule("editor/EditorManager"),
        CommandManager      = brackets.getModule("command/CommandManager"),
        Menus               = brackets.getModule("command/Menus"),
        Commands            = brackets.getModule("command/Commands"),
        KeyBindingManager   = brackets.getModule("command/KeyBindingManager"),
        AppInit             = brackets.getModule("utils/AppInit"),

        // Constants
        CHAR        = "character",
        WORD        = "word",
        LINE        = "line",
        MAX_LINE_LENGTH = 1000,

        // Text Selection Ring
        ring        = [],
        ringIndex   = 0,
        ringSize    = 15,

        // Mark
        isMarkSet   = false;

    function setMarkCommand() {
        isMarkSet = !isMarkSet;

        console.log("Mark " + (isMarkSet ? "un" : "") + "set");
    }

    function _killRingSave(selectedText) {
        if (!selectedText) {
            return;
        }
        ring[ringIndex % ringSize] = selectedText;
        ringIndex++;
    }

    function killRingSave() {
        var editor  = EditorManager.getFocusedEditor();
        _killRingSave(editor.getSelectedText());
    }

    function killRegion() {
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            selection   = editor.getSelection();
        _killRingSave(editor.getSelectedText());
        doc.replaceRange("", selection.start, selection.end);
    }

    function yank() {
        if (ring.length === 0) {
            return;
        }
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            cursorPos   = editor.getCursorPos();
        doc.replaceRange(ring[(ringIndex - 1) % ringSize], cursorPos);
    }

    function iSearchBackward() {
        // @todo: stub
    }

    /**
     * Function to move the cursor
     *
     * @param   {number}    unit        Number of units to move
     * @param   {number}    type        CHAR|WORD|LINE
     * @param   {boolean}   absolute    Flag to specify if the cursor isn't moved relative to the current
     *                                  position
     */
    function moveCursor(unit, type, absolute) {
        var editor      = EditorManager.getFocusedEditor(),
            cursorPos   = editor.getCursorPos(),
            line        = cursorPos.line,
            column        = cursorPos.ch;
        switch (type) {
        case CHAR:
            column += unit - (absolute ? column : 0);
            break;
        case LINE:
            line += unit - (absolute ? line : 0);
            break;
        case WORD:
            if (Math.abs(unit) !== 1) {
                console.error("Cursor positioning for multiple words is not supported");
                return;
            }
            var text = editor.document.getLine(line),
                lineLength = text.length;
            if (unit === 1) {
                text = text.substring(column);
            } else {
                // @todo: use a better implementation for reversing a string
                // http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
                text = text.split("").reverse().join("").substring(lineLength - column);
            }

            var indexOfNextWord = text.search(/\W\w/) + 1;
            if (indexOfNextWord > 0) {
                column += (unit * indexOfNextWord) - (absolute ? column : 0);
            } else {
                line += unit > 0 ? 1 : -1;
                column = MAX_LINE_LENGTH;
            }
            break;
        }
        editor.setCursorPos(line, column);
    }

    AppInit.appReady(function () {

        var menus = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU),

            // Command Ids
            MOVE_BEGINNING_OF_LINE  = "emacs.move-beginning-of-line",
            MOVE_END_OF_LINE        = "emacs.move-end-of-line",
            YANK                    = "emacs.yank",
            KILL_REGION             = "emacs.kill-region",
            KILL_RING_SAVE          = "emacs.kill-ring-save",
            FORWARD_CHAR            = "emacs.forward-char",
            BACKWARD_CHAR           = "emacs.backward-char",
            FORWARD_WORD            = "emacs.forward-word",
            BACKWARD_WORD           = "emacs.backward-word",
            PREVIOUS_LINE           = "emacs.previous-line",
            NEXT_LINE               = "emacs.next-line",
            PREFIX_COMMAND          = "emacs.prefix-command",
            UNDO                    = "emacs.undo",
            ISEARCH_FORWARD         = "emacs.isearch-forward",
            FIND_FILE               = "emacs.find-file",
            SAVE_BUFFER             = "emacs.save-buffer",
            COMMENT_DWIM            = "emacs.comment-dwim",
            // .. not implemented ..
            SET_MARK_COMMAND        = "emacs.set-mark-command",
            ISEARCH_BACKWARD        = "emacs.isearch-backward",

            /*
             * Emacs commands
             *
             * Find list of commands in emacs: Ctrl-h b
             */
            commands = [
                {
                    id:         MOVE_BEGINNING_OF_LINE,
                    name:       "Move Beginning of Line",
                    keyBinding: "Ctrl-A",
                    callback:   moveCursor.bind(this, 0, CHAR, true)
                },
                {
                    id:         MOVE_END_OF_LINE,
                    name:       "Move End of Line",
                    keyBinding: "Ctrl-E",
                    callback:   moveCursor.bind(this, MAX_LINE_LENGTH, CHAR, true)
                },
                {
                    id:         YANK,
                    name:       "Yank",
                    keyBinding: "Ctrl-Y",
                    callback:   yank
                },
                {
                    id:         KILL_REGION,
                    name:       "Kill Region",
                    keyBinding: "Ctrl-W",
                    callback:   killRegion
                },
                {
                    id:         KILL_RING_SAVE,
                    name:       "Kill Ring Save",
                    keyBinding: "Alt-W",
                    callback:   killRingSave
                },
                {
                    id:         ISEARCH_BACKWARD,
                    name:       "Incremental Search Backward",
                    keyBinding: "Ctrl-R",
                    callback:   iSearchBackward
                },
                {
                    id:         FORWARD_CHAR,
                    name:       "Forward Character",
                    keyBinding: "Ctrl-F",
                    callback:   moveCursor.bind(this, 1, CHAR)
                },
                {
                    id:         BACKWARD_CHAR,
                    name:       "Backward Character",
                    keyBinding: "Ctrl-B",
                    callback:   moveCursor.bind(this, -1, CHAR)
                },
                {
                    id:         FORWARD_WORD,
                    name:       "Forward Word",
                    keyBinding: "Alt-F",
                    callback:   moveCursor.bind(this, 1, WORD)
                },
                {
                    id:         BACKWARD_WORD,
                    name:       "Backward Word",
                    keyBinding: "Alt-B",
                    callback:   moveCursor.bind(this, -1, WORD)
                },
                {
                    id:         NEXT_LINE,
                    name:       "Next Line",
                    keyBinding: "Ctrl-N",
                    callback:   moveCursor.bind(this, 1, LINE)
                },
                {
                    id:         PREVIOUS_LINE,
                    name:       "Previous Line",
                    keyBinding: "Ctrl-P",
                    callback:   moveCursor.bind(this, -1, LINE)
                },
                {
                    id:         PREFIX_COMMAND,
                    name:       "Prefix Command",
                    keyBinding: "Ctrl-X",
                    commands:   [
                        {
                            id:         FIND_FILE,
                            keyBinding: "Ctrl-F",
                            override:   Commands.FILE_OPEN
                        },
                        {
                            id:         SAVE_BUFFER,
                            keyBinding: "Ctrl-S",
                            override:   Commands.FILE_SAVE
                        }
                    ]
                },
                {
                    id:         UNDO,
                    name:       "Undo",
                    keyBinding: "Ctrl-/",
                    override:   Commands.EDIT_UNDO
                },
                {
                    id:         COMMENT_DWIM,
                    name:       "Comment (Do What I Mean)",
                    keyBinding: "Alt-;",
                    override:   Commands.EDIT_LINE_COMMENT
                },
                {
                    id:         ISEARCH_FORWARD,
                    name:       "ISearch Forward",
                    keyBinding: "Ctrl-S",
                    override:   Commands.EDIT_FIND
                }
//              {
//                  id:         SET_MARK_COMMAND,
//                  name:       "Set Mark Command",
//                  keyBinding: "Ctrl-Space",
//                  callback:   setMarkCommand
//              },
            ];

        /**
         * EventHandler Class
         *
         * Executes relevant commands when any of the specified keybindings are used.
         *
         * @param   {Array} commands    Commands that can be used for the next keybinding.
         *
         * @todo: move the EventHandler to a separate module
         */
        function EventHandler(allCommands) {
            this.availableCommands = allCommands; // @todo: no need to copy array, right?
        }

        EventHandler.prototype.commands = commands;

        EventHandler.prototype.availableCommands = undefined; // set on instantiation

        EventHandler.prototype.getCommand = function (keyBinding) {
            var command = this.availableCommands.filter(function find(command) {
                return (command.keyBinding === keyBinding) ? command : false;
            });
            if (command.length === 0) { // not found
                return false;
            }
            return command[0]; // get the first match, there should only be one
        };

        /**
         * Function for reseting the context i.e. the number of available commands are not dependent on the last keyBinding used
         *
         * @param   {Array} commands    Commands that can be used for the next keybinding.
         */
        EventHandler.prototype.resetContext = function (commands) {
            this.availableCommands = commands || this.commands;
        };

        EventHandler.prototype.handle = function (keyBinding) {
            // Get the command to execute based on the stack
            var command = this.getCommand(keyBinding);

            if (!command) {
                this.resetContext();
                return;
            }

            if (!command.commands) {
                if (command.override) {
                    CommandManager.execute(command.override);
                } else {
                    command.callback();
                }
            }

            // Update the context
            this.resetContext(command.commands || undefined);
        };

        var handler = new EventHandler(commands);

        function removeBinding(command) {
            KeyBindingManager.removeBinding(command.keyBinding);
            if (typeof command.commands !== "undefined" && command.commands.length > 0) {
                command.commands.forEach(removeBinding);
            }
        }

        function addBinding(command) {
            KeyBindingManager.addBinding(command.id, command.keyBinding);
        }

        function register(command) {
            CommandManager.register(command.name,
                                    command.id,
                                    handler.handle.bind(handler, command.keyBinding));
            menus.addMenuItem(command.id);
        }

        // @todo: using setTimeout since keybinding module takes some time to load
        window.setTimeout(function () {
            menus.addMenuItem(Menus.DIVIDER);
            commands.forEach(removeBinding);
            commands.forEach(register);
            commands.forEach(addBinding);
        }, 500);

    });
});<commit_msg>Commented out functionality not being used.<commit_after>/*jslint vars: true, plusplus: true, devel: true, browser: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, brackets, console*/
define(function (require, exports, module) {
    'use strict';

    var EditorManager       = brackets.getModule("editor/EditorManager"),
        CommandManager      = brackets.getModule("command/CommandManager"),
        Menus               = brackets.getModule("command/Menus"),
        Commands            = brackets.getModule("command/Commands"),
        KeyBindingManager   = brackets.getModule("command/KeyBindingManager"),
        AppInit             = brackets.getModule("utils/AppInit"),

        // Constants
        CHAR        = "character",
        WORD        = "word",
        LINE        = "line",
        MAX_LINE_LENGTH = 1000,

//        // Mark
//        isMarkSet   = false;

        // Text Selection Ring
        ring        = [],
        ringIndex   = 0,
        ringSize    = 15;

//    function setMarkCommand() {
//        isMarkSet = !isMarkSet;
//
//        console.log("Mark " + (isMarkSet ? "un" : "") + "set");
//    }

    function _killRingSave(selectedText) {
        if (!selectedText) {
            return;
        }
        ring[ringIndex % ringSize] = selectedText;
        ringIndex++;
    }

    function killRingSave() {
        var editor  = EditorManager.getFocusedEditor();
        _killRingSave(editor.getSelectedText());
    }

    function killRegion() {
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            selection   = editor.getSelection();
        _killRingSave(editor.getSelectedText());
        doc.replaceRange("", selection.start, selection.end);
    }

    function yank() {
        if (ring.length === 0) {
            return;
        }
        var editor      = EditorManager.getFocusedEditor(),
            doc         = editor.document,
            cursorPos   = editor.getCursorPos();
        doc.replaceRange(ring[(ringIndex - 1) % ringSize], cursorPos);
    }

//    function iSearchBackward() {
//        // @todo: stub
//    }

    /**
     * Function to move the cursor
     *
     * @param   {number}    unit        Number of units to move
     * @param   {number}    type        CHAR|WORD|LINE
     * @param   {boolean}   absolute    Flag to specify if the cursor isn't moved relative to the current
     *                                  position
     */
    function moveCursor(unit, type, absolute) {
        var editor      = EditorManager.getFocusedEditor(),
            cursorPos   = editor.getCursorPos(),
            line        = cursorPos.line,
            column        = cursorPos.ch;
        switch (type) {
        case CHAR:
            column += unit - (absolute ? column : 0);
            break;
        case LINE:
            line += unit - (absolute ? line : 0);
            break;
        case WORD:
            if (Math.abs(unit) !== 1) {
                console.error("Cursor positioning for multiple words is not supported");
                return;
            }
            var text = editor.document.getLine(line),
                lineLength = text.length;
            if (unit === 1) {
                text = text.substring(column);
            } else {
                // @todo: use a better implementation for reversing a string
                // http://eddmann.com/posts/ten-ways-to-reverse-a-string-in-javascript/
                text = text.split("").reverse().join("").substring(lineLength - column);
            }

            var indexOfNextWord = text.search(/\W\w/) + 1;
            if (indexOfNextWord > 0) {
                column += (unit * indexOfNextWord) - (absolute ? column : 0);
            } else {
                line += unit > 0 ? 1 : -1;
                column = MAX_LINE_LENGTH;
            }
            break;
        }
        editor.setCursorPos(line, column);
    }

    AppInit.appReady(function () {

        var menus = Menus.getMenu(Menus.AppMenuBar.VIEW_MENU),

            // Command Ids
            MOVE_BEGINNING_OF_LINE  = "emacs.move-beginning-of-line",
            MOVE_END_OF_LINE        = "emacs.move-end-of-line",
            YANK                    = "emacs.yank",
            KILL_REGION             = "emacs.kill-region",
            KILL_RING_SAVE          = "emacs.kill-ring-save",
            FORWARD_CHAR            = "emacs.forward-char",
            BACKWARD_CHAR           = "emacs.backward-char",
            FORWARD_WORD            = "emacs.forward-word",
            BACKWARD_WORD           = "emacs.backward-word",
            PREVIOUS_LINE           = "emacs.previous-line",
            NEXT_LINE               = "emacs.next-line",
            PREFIX_COMMAND          = "emacs.prefix-command",
            UNDO                    = "emacs.undo",
            ISEARCH_FORWARD         = "emacs.isearch-forward",
            FIND_FILE               = "emacs.find-file",
            SAVE_BUFFER             = "emacs.save-buffer",
            COMMENT_DWIM            = "emacs.comment-dwim",
            // .. not implemented ..
            SET_MARK_COMMAND        = "emacs.set-mark-command",
            ISEARCH_BACKWARD        = "emacs.isearch-backward",

            /*
             * Emacs commands
             *
             * Find list of commands in emacs: Ctrl-h b
             */
            commands = [
                {
                    id:         MOVE_BEGINNING_OF_LINE,
                    name:       "Move Beginning of Line",
                    keyBinding: "Ctrl-A",
                    callback:   moveCursor.bind(this, 0, CHAR, true)
                },
                {
                    id:         MOVE_END_OF_LINE,
                    name:       "Move End of Line",
                    keyBinding: "Ctrl-E",
                    callback:   moveCursor.bind(this, MAX_LINE_LENGTH, CHAR, true)
                },
                {
                    id:         YANK,
                    name:       "Yank",
                    keyBinding: "Ctrl-Y",
                    callback:   yank
                },
                {
                    id:         KILL_REGION,
                    name:       "Kill Region",
                    keyBinding: "Ctrl-W",
                    callback:   killRegion
                },
                {
                    id:         KILL_RING_SAVE,
                    name:       "Kill Ring Save",
                    keyBinding: "Alt-W",
                    callback:   killRingSave
                },
//                {
//                    id:         ISEARCH_BACKWARD,
//                    name:       "Incremental Search Backward",
//                    keyBinding: "Ctrl-R",
//                    callback:   iSearchBackward
//                },
                {
                    id:         FORWARD_CHAR,
                    name:       "Forward Character",
                    keyBinding: "Ctrl-F",
                    callback:   moveCursor.bind(this, 1, CHAR)
                },
                {
                    id:         BACKWARD_CHAR,
                    name:       "Backward Character",
                    keyBinding: "Ctrl-B",
                    callback:   moveCursor.bind(this, -1, CHAR)
                },
                {
                    id:         FORWARD_WORD,
                    name:       "Forward Word",
                    keyBinding: "Alt-F",
                    callback:   moveCursor.bind(this, 1, WORD)
                },
                {
                    id:         BACKWARD_WORD,
                    name:       "Backward Word",
                    keyBinding: "Alt-B",
                    callback:   moveCursor.bind(this, -1, WORD)
                },
                {
                    id:         NEXT_LINE,
                    name:       "Next Line",
                    keyBinding: "Ctrl-N",
                    callback:   moveCursor.bind(this, 1, LINE)
                },
                {
                    id:         PREVIOUS_LINE,
                    name:       "Previous Line",
                    keyBinding: "Ctrl-P",
                    callback:   moveCursor.bind(this, -1, LINE)
                },
                {
                    id:         PREFIX_COMMAND,
                    name:       "Prefix Command",
                    keyBinding: "Ctrl-X",
                    commands:   [
                        {
                            id:         FIND_FILE,
                            keyBinding: "Ctrl-F",
                            override:   Commands.FILE_OPEN
                        },
                        {
                            id:         SAVE_BUFFER,
                            keyBinding: "Ctrl-S",
                            override:   Commands.FILE_SAVE
                        }
                    ]
                },
                {
                    id:         UNDO,
                    name:       "Undo",
                    keyBinding: "Ctrl-/",
                    override:   Commands.EDIT_UNDO
                },
                {
                    id:         COMMENT_DWIM,
                    name:       "Comment (Do What I Mean)",
                    keyBinding: "Alt-;",
                    override:   Commands.EDIT_LINE_COMMENT
                },
                {
                    id:         ISEARCH_FORWARD,
                    name:       "ISearch Forward",
                    keyBinding: "Ctrl-S",
                    override:   Commands.EDIT_FIND
                }
//              {
//                  id:         SET_MARK_COMMAND,
//                  name:       "Set Mark Command",
//                  keyBinding: "Ctrl-Space",
//                  callback:   setMarkCommand
//              }
            ];

        /**
         * EventHandler Class
         *
         * Executes relevant commands when any of the specified keybindings are used.
         *
         * @param   {Array} commands    Commands that can be used for the next keybinding.
         *
         * @todo: move the EventHandler to a separate module
         */
        function EventHandler(allCommands) {
            this.availableCommands = allCommands; // @todo: no need to copy array, right?
        }

        EventHandler.prototype.commands = commands;

        EventHandler.prototype.availableCommands = undefined; // set on instantiation

        EventHandler.prototype.getCommand = function (keyBinding) {
            var command = this.availableCommands.filter(function find(command) {
                return (command.keyBinding === keyBinding) ? command : false;
            });
            if (command.length === 0) { // not found
                return false;
            }
            return command[0]; // get the first match, there should only be one
        };

        /**
         * Function for reseting the context i.e. the number of available commands are not dependent on the last keyBinding used
         *
         * @param   {Array} commands    Commands that can be used for the next keybinding.
         */
        EventHandler.prototype.resetContext = function (commands) {
            this.availableCommands = commands || this.commands;
        };

        EventHandler.prototype.handle = function (keyBinding) {
            // Get the command to execute based on the stack
            var command = this.getCommand(keyBinding);

            if (!command) {
                this.resetContext();
                return;
            }

            if (!command.commands) {
                if (command.override) {
                    CommandManager.execute(command.override);
                } else {
                    command.callback();
                }
            }

            // Update the context
            this.resetContext(command.commands || undefined);
        };

        var handler = new EventHandler(commands);

        function removeBinding(command) {
            KeyBindingManager.removeBinding(command.keyBinding);
            if (typeof command.commands !== "undefined" && command.commands.length > 0) {
                command.commands.forEach(removeBinding);
            }
        }

        function addBinding(command) {
            KeyBindingManager.addBinding(command.id, command.keyBinding);
        }

        function register(command) {
            CommandManager.register(command.name,
                                    command.id,
                                    handler.handle.bind(handler, command.keyBinding));
            menus.addMenuItem(command.id);
        }

        // @todo: using setTimeout since keybinding module takes some time to load
        window.setTimeout(function () {
            menus.addMenuItem(Menus.DIVIDER);
            commands.forEach(removeBinding);
            commands.forEach(register);
            commands.forEach(addBinding);
        }, 500);

    });
});<|endoftext|>


<commit_before>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.
var Menu = require('menu');
var Dialog = require('dialog');
var Fs = require('fs');

// Report crashes to our server.
require('crash-reporter').start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is GCed.
var mainWindow = null;

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

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  var template = [
    {
      label: 'Electron',
      submenu: [
        {
          label: 'About Electron',
          selector: 'orderFrontStandardAboutPanel:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: 'Hide Electron',
          accelerator: 'CmdOrCtrl+H',
          selector: 'hide:'
        },
        {
          label: 'Hide Others',
          accelerator: 'CmdOrCtrl+Shift+H',
          selector: 'hideOtherApplications:'
        },
        {
          label: 'Show All',
          selector: 'unhideAllApplications:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Quit',
          accelerator: 'CmdOrCtrl+Q',
          selector: 'terminate:'
        },
      ]
    },
    {
      label: 'File',
      submenu: [
        {
          label: 'New',
          accelerator: 'CmdOrCtrl+N',
          click: function() { createWindow(); }
        },
        {
          label: 'Open..',
          accelerator: 'CmdOrCtrl+O',
          click: function() { openFile(); }
        },
        {
          label: 'Save As..',
          accelerator: 'Shift+CmdOrCtrl+S',
          click: function() { saveFile(); }
        },
      ]
    },
    {
      label: 'Edit',
      submenu: [
        {
          label: 'Undo',
          accelerator: 'CmdOrCtrl+Z',
          selector: 'undo:'
        },
        {
          label: 'Redo',
          accelerator: 'Shift+CmdOrCtrl+Z',
          selector: 'redo:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Cut',
          accelerator: 'CmdOrCtrl+X',
          selector: 'cut:'
        },
        {
          label: 'Copy',
          accelerator: 'CmdOrCtrl+C',
          selector: 'copy:'
        },
        {
          label: 'Paste',
          accelerator: 'CmdOrCtrl+V',
          selector: 'paste:'
        },
        {
          label: 'Select All',
          accelerator: 'CmdOrCtrl+A',
          selector: 'selectAll:'
        }
      ]
    },
    {
      label: 'View',
      submenu: [
        {
          label: 'Reload',
          accelerator: 'CmdOrCtrl+R',
          click: function() { BrowserWindow.getFocusedWindow().reload(); }
        },
        {
          label: 'Toggle DevTools',
          accelerator: 'Alt+CmdOrCtrl+I',
          click: function() { BrowserWindow.getFocusedWindow().toggleDevTools(); }
        },
      ]
    },
    {
      label: 'Window',
      submenu: [
        {
          label: 'Minimize',
          accelerator: 'CmdOrCtrl+M',
          selector: 'performMiniaturize:'
        },
        {
          label: 'Close',
          accelerator: 'CmdOrCtrl+W',
          selector: 'performClose:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Bring All to Front',
          selector: 'arrangeInFront:'
        }
      ]
    },
    {
      label: 'Help',
      submenu: []
    }
  ];

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

  // Create the browser window.
  createWindow();
});

function createWindow(data, title) {
  data = typeof data !== 'undefined' ? data : '"","",""';
  title = typeof title !== 'undefined' ? title : "Untitled.csv";

  mainWindow = new BrowserWindow({width: 800, height: 600});

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // Open the devtools.
  mainWindow.openDevTools();
  mainWindow.title = title;

  mainWindow.webContents.on('did-finish-load', function() {
    mainWindow.webContents.send('loadData', data);
  });

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
}

function openFile() {
  Dialog.showOpenDialog({ filters: [
    { name: 'text', extensions: ['csv'] }
  ]}, function (fileNames) {
      if (fileNames === undefined) return;
      var fileName = fileNames[0];
      Fs.readFile(fileName, 'utf-8', function (err, data) {
        createWindow(data, fileName);
      });
  });
}

function saveFile() {
  window = BrowserWindow.getFocusedWindow();
  Dialog.showSaveDialog({ filters: [
    { name: 'text', extensions: ['csv'] }
  ]}, function (fileName) {
    if (fileName === undefined) return;
    window.webContents.send('saveData', fileName);
  });
}
<commit_msg>Import first workbook sheet<commit_after>var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.
var Menu = require('menu');
var Dialog = require('dialog');
var Fs = require('fs');
var XLSX = require('xlsx');

// Report crashes to our server.
require('crash-reporter').start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is GCed.
var mainWindow = null;

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

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
app.on('ready', function() {
  var template = [
    {
      label: 'Electron',
      submenu: [
        {
          label: 'About Electron',
          selector: 'orderFrontStandardAboutPanel:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Services',
          submenu: []
        },
        {
          type: 'separator'
        },
        {
          label: 'Hide Electron',
          accelerator: 'CmdOrCtrl+H',
          selector: 'hide:'
        },
        {
          label: 'Hide Others',
          accelerator: 'CmdOrCtrl+Shift+H',
          selector: 'hideOtherApplications:'
        },
        {
          label: 'Show All',
          selector: 'unhideAllApplications:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Quit',
          accelerator: 'CmdOrCtrl+Q',
          selector: 'terminate:'
        },
      ]
    },
    {
      label: 'File',
      submenu: [
        {
          label: 'New',
          accelerator: 'CmdOrCtrl+N',
          click: function() { createWindow(); }
        },
        {
          label: 'Open..',
          accelerator: 'CmdOrCtrl+O',
          click: function() { openFile(); }
        },
        {
          label: 'Import Excel file',
          click: function() { importExcel(); }
        },
        {
          label: 'Save As..',
          accelerator: 'Shift+CmdOrCtrl+S',
          click: function() { saveFile(); }
        },
      ]
    },
    {
      label: 'Edit',
      submenu: [
        {
          label: 'Undo',
          accelerator: 'CmdOrCtrl+Z',
          selector: 'undo:'
        },
        {
          label: 'Redo',
          accelerator: 'Shift+CmdOrCtrl+Z',
          selector: 'redo:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Cut',
          accelerator: 'CmdOrCtrl+X',
          selector: 'cut:'
        },
        {
          label: 'Copy',
          accelerator: 'CmdOrCtrl+C',
          selector: 'copy:'
        },
        {
          label: 'Paste',
          accelerator: 'CmdOrCtrl+V',
          selector: 'paste:'
        },
        {
          label: 'Select All',
          accelerator: 'CmdOrCtrl+A',
          selector: 'selectAll:'
        }
      ]
    },
    {
      label: 'View',
      submenu: [
        {
          label: 'Reload',
          accelerator: 'CmdOrCtrl+R',
          click: function() { BrowserWindow.getFocusedWindow().reload(); }
        },
        {
          label: 'Toggle DevTools',
          accelerator: 'Alt+CmdOrCtrl+I',
          click: function() { BrowserWindow.getFocusedWindow().toggleDevTools(); }
        },
      ]
    },
    {
      label: 'Window',
      submenu: [
        {
          label: 'Minimize',
          accelerator: 'CmdOrCtrl+M',
          selector: 'performMiniaturize:'
        },
        {
          label: 'Close',
          accelerator: 'CmdOrCtrl+W',
          selector: 'performClose:'
        },
        {
          type: 'separator'
        },
        {
          label: 'Bring All to Front',
          selector: 'arrangeInFront:'
        }
      ]
    },
    {
      label: 'Help',
      submenu: []
    }
  ];

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

  // Create the browser window.
  createWindow();
});

function createWindow(data, title) {
  data = typeof data !== 'undefined' ? data : '"","",""';
  title = typeof title !== 'undefined' ? title : "Untitled.csv";

  mainWindow = new BrowserWindow({width: 800, height: 600});

  // and load the index.html of the app.
  mainWindow.loadUrl('file://' + __dirname + '/index.html');

  // Open the devtools.
  mainWindow.openDevTools();
  mainWindow.title = title;

  mainWindow.webContents.on('did-finish-load', function() {
    mainWindow.webContents.send('loadData', data);
  });

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
}

function openFile() {
  Dialog.showOpenDialog({ filters: [
    { name: 'text', extensions: ['csv'] }
  ]}, function (fileNames) {
      if (fileNames === undefined) return;
      var fileName = fileNames[0];
      Fs.readFile(fileName, 'utf-8', function (err, data) {
        createWindow(data, fileName);
      });
  });
}

function saveFile() {
  window = BrowserWindow.getFocusedWindow();
  Dialog.showSaveDialog({ filters: [
    { name: 'text', extensions: ['csv'] }
  ]}, function (fileName) {
    if (fileName === undefined) return;
    window.webContents.send('saveData', fileName);
  });
}

function importExcel() {
  Dialog.showOpenDialog({ filters: [
    { name: 'text', extensions: ['xlsx', 'xls'] }
  ]}, function (fileNames) {
      if (fileNames === undefined) return;
      var fileName = fileNames[0];
      var workbook = XLSX.readFile(fileName);
      var first_sheet_name = workbook.SheetNames[0];
      var worksheet = workbook.Sheets[first_sheet_name];
      data = XLSX.utils.sheet_to_csv(worksheet);
      createWindow(data);
  });
}
<|endoftext|>


<commit_before>"use strict";

import "babel-polyfill";
import qs from "qs";
import Auth from "./quiz/auth.js";
import Quiz from "./quiz/quiz.js";
import Question from "./quiz/question.js";
import config from "./config.js";
import redis from "redis";

const redisClient = redis.createClient();
const bot = config.bot;

bot.onText(/\/start/, function onText(msg) {
  showQuizList(msg);
});

function showQuizList(msg) {
  const chatId = msg.chat.id;
  Auth.getUser(chatId).then(
    res => {
      Quiz.showList(msg, bot);
    },
    error => {
      console.error(error);
    }
  );
}

// NOTE: callback data should be very small, otherwise you'll see 400 error
bot.on("callback_query", msg => {
  const chatId = msg.message.chat.id;
  let json = {};
  try {
    json = qs.parse(msg.data);
  } catch (error) {
    console.error("Invalid query.");
    bot.sendMessage(chatId, "Invalid query.");
  }
  if (json.action) {
    switch (json.action) {
      case "get_quiz":
        Quiz.show(chatId, json);
        break;
      case "answer_question":
        Question.handleAnswer(chatId, json);
        break;
      default:
        console.error("Unknown callback query.");
        break;
    }
  }
});

// JUST FOR DEVELOPMENT
// ------------------------------------------
bot.onText(/\/d/, function onText(msg) {
  redisClient.del(`${msg.chat.id}-user`);
  bot.sendMessage(msg.chat.id, "User Removed.");
});

bot.onText(/\/r/, function onText(msg) {
  const chatId = msg.chat.id;

  Auth.getUser(chatId).then(
    res => {
      console.log(res.user);
    },
    error => {
      console.error(error);
    }
  );
});<commit_msg>Add answerCallbackQuery to prevent waiting<commit_after>"use strict";

import "babel-polyfill";
import qs from "qs";
import Auth from "./quiz/auth.js";
import Quiz from "./quiz/quiz.js";
import Question from "./quiz/question.js";
import config from "./config.js";
import redis from "redis";

const redisClient = redis.createClient();
const bot = config.bot;

bot.onText(/\/start/, function onText(msg) {
  showQuizList(msg);
});

function showQuizList(msg) {
  const chatId = msg.chat.id;
  Auth.getUser(chatId).then(
    res => {
      Quiz.showList(msg, bot);
    },
    error => {
      console.error(error);
    }
  );
}

// NOTE: callback data should be very small, otherwise you'll see 400 error
bot.on("callback_query", msg => {
  const chatId = msg.message.chat.id;
  let json = {};
  try {
    json = qs.parse(msg.data);
  } catch (error) {
    console.error("Invalid query.");
    bot.sendMessage(chatId, "Invalid query.");
  }
  if (json.action) {
    switch (json.action) {
      case "get_quiz":
        Quiz.show(chatId, json);
        break;
      case "answer_question":
        Question.handleAnswer(chatId, json);
        break;
      default:
        console.error("Unknown callback query.");
        break;
    }
    bot.answerCallbackQuery(msg.id);
  }
});

// JUST FOR DEVELOPMENT
// ------------------------------------------
bot.onText(/\/d/, function onText(msg) {
  redisClient.del(`${msg.chat.id}-user`);
  bot.sendMessage(msg.chat.id, "User Removed.");
});

bot.onText(/\/r/, function onText(msg) {
  const chatId = msg.chat.id;

  Auth.getUser(chatId).then(
    res => {
      console.log(res.user);
    },
    error => {
      console.error(error);
    }
  );
});
<|endoftext|>


<commit_before>const electron = require('electron');
const ipc = electron.ipcMain;

var menubar = require('menubar');
var path = require('path');

require('crash-reporter').start();

var AutoLaunch = require('auto-launch');
var dialog = require('dialog');

// Status icons
var iconIdle = path.join(__dirname, 'images', 'tray-idleTemplate.png');
var iconActive = path.join(__dirname, 'images', 'tray-active.png');

// Utilities
var isLinux = (process.platform === 'linux');
var isDarwin = (process.platform === 'darwin');
var isWindows = (process.platform === 'win32');

// The auto-start module does not support Linux
if (!isLinux) {
  var autoStart = new AutoLaunch({
    name: 'Gitify'
  });
}

// Create menu
var mb = menubar({
  index: 'file://' + __dirname + '/index.html',
  icon: iconIdle,
  preloadWindow: true,
  width: 420,
  height: 370,
  resizable: false,
  'standard-window': false
});

// Application code
mb.on('ready', function () {
  // Auto-update not working on Linux and Windows
  if (isDarwin) {
    checkAutoUpdate(false);
  }

  this.on('show', function () {
    var screen = require('screen');
    var cursorPointer = screen.getCursorScreenPoint();
    var displaySize = screen.getPrimaryDisplay().workAreaSize;

    // Determination of the position of the pane with an icon
    var x = (cursorPointer.x < (displaySize.width / 2)) ? 'left' : 'right';
    var y = (cursorPointer.y < (displaySize.height / 2)) ? 'top' : 'bottom';

    // If click was made above middle (axis X and Y), then recalculate window position
    if (x === 'right' && y === 'bottom') {
      mb.setOption('window-position', (isWindows) ? 'trayBottomCenter' : 'bottomRight');
    } else if (x === 'right' && y === 'top') {
      mb.setOption('window-position', 'trayCenter');
    } else if (x === 'left' && y === 'bottom') {
      mb.setOption('window-position', 'bottomLeft');
    } else if (x === 'left' && y === 'top') {
      mb.setOption('window-position', 'trayCenter');
    }
  });

  function checkAutoUpdate (showAlert) {
    var autoUpdateOptions = {
      repo: 'ekonstantinidis/gitify',
      currentVersion: mb.app.getVersion()
    };

    var ghReleases = require('electron-gh-releases');
    var update = new ghReleases(autoUpdateOptions, function (autoUpdater) {
      autoUpdater
        .on('error', function (event, message) {
          console.log('ERRORED.');
          console.log('Event: ' + JSON.stringify(event) + '. MESSAGE: ' + message);
        })
        .on('update-downloaded', function (event, releaseNotes, releaseName,
                                           releaseDate, updateUrl, quitAndUpdate) {
          console.log('Update downloaded');
          confirmAutoUpdate(quitAndUpdate);
        });
    });

    // Check for updates
    update.check(function (err, status) {
      if (err || !status) {
        if (showAlert) {
          dialog.showMessageBox({
            type: 'info',
            buttons: ['Close'],
            title: 'No update available',
            message: 'You are currently running the latest version of Gitify.'
          });
        }

        if (isDarwin) {
          mb.app.dock.hide();
        }
      }

      if (!err && status) {
        update.download();
      }
    });
  }

  function confirmAutoUpdate (quitAndUpdate) {
    dialog.showMessageBox({
      type: 'question',
      buttons: ['Update & Restart', 'Cancel'],
      title: 'Update Available',
      cancelId: 99,
      message: 'There is an update available. Would you like to update Gitify now?'
    }, function (response) {
      console.log('Exit: ' + response);
      if (isDarwin) {
        mb.app.dock.hide();
      }

      if (response === 0) {
        quitAndUpdate();
      }
    });
  }

  ipc.on('reopen-window', function () {
    mb.window.show();
  });

  ipc.on('update-icon', function (event, arg) {
    if (arg === 'TrayActive') {
      mb.tray.setImage(iconActive);
    } else {
      mb.tray.setImage(iconIdle);
    }
  });

  ipc.on('startup-enable', function () {
    if (!isLinux) {
      autoStart.enable();
    }
  });

  ipc.on('startup-disable', function () {
    if (!isLinux) {
      autoStart.disable();
    }
  });

  ipc.on('check-update', function () {
    if (isDarwin) {
      checkAutoUpdate(true);
    }
  });

  ipc.on('app-quit', function () {
    mb.app.quit();
  });

  mb.tray.setToolTip('GitHub Notifications on your menu bar.');
});
<commit_msg>Revert "ooops"<commit_after>const electron = require('electron');
const ipc = electron.ipcMain;

var menubar = require('menubar');
var path = require('path');

require('crash-reporter').start();

var AutoLaunch = require('auto-launch');
var dialog = require('dialog');

// Status icons
var iconIdle = path.join(__dirname, 'images', 'tray-idleTemplate.png');
var iconActive = path.join(__dirname, 'images', 'tray-active.png');

// Utilities
var isLinux = (process.platform === 'linux');
var isDarwin = (process.platform === 'darwin');
var isWindows = (process.platform === 'win32');

// The auto-start module does not support Linux
if (!isLinux) {
  var autoStart = new AutoLaunch({
    name: 'Gitify'
  });
}

// Create menu
var mb = menubar({
  index: 'file://' + __dirname + '/index.html',
  icon: iconIdle,
  preloadWindow: true,
  width: 420,
  height: 370,
  resizable: false,
  'standard-window': false
});

// Application code
mb.on('ready', function () {
  // Auto-update not working on Linux and Windows
  if (isDarwin) {
    checkAutoUpdate(false);
  }

  this.on('show', function () {
    var screen = require('screen');
    var cursorPointer = screen.getCursorScreenPoint();
    var displaySize = screen.getPrimaryDisplay().workAreaSize;

    // Determination of the position of the pane with an icon
    var x = (cursorPointer.x < (displaySize.width / 2)) ? 'left' : 'right';
    var y = (cursorPointer.y < (displaySize.height / 2)) ? 'top' : 'bottom';

    // If click was made above middle (axis X and Y), then recalculate window position
    if (x === 'right' && y === 'bottom') {
      mb.setOption('window-position', (isWindows) ? 'trayBottomCenter' : 'bottomRight');
    } else if (x === 'right' && y === 'top') {
      mb.setOption('window-position', 'trayCenter');
    } else if (x === 'left' && y === 'bottom') {
      mb.setOption('window-position', 'bottomLeft');
    } else if (x === 'left' && y === 'top') {
      mb.setOption('window-position', 'trayCenter');
    }
  });

  function checkAutoUpdate (showAlert) {
    var autoUpdateOptions = {
      repo: 'ekonstantinidis/gitify',
      currentVersion: mb.app.getVersion()
    };

    var ghReleases = require('electron-gh-releases');
    var update = new ghReleases(autoUpdateOptions, function (autoUpdater) {
      autoUpdater
        .on('error', function (event, message) {
          console.log('ERRORED.');
          console.log('Event: ' + JSON.stringify(event) + '. MESSAGE: ' + message);
        })
        .on('update-downloaded', function (event, releaseNotes, releaseName,
                                           releaseDate, updateUrl, quitAndUpdate) {
          console.log('Update downloaded');
          confirmAutoUpdate(quitAndUpdate);
        });
    });

    // Check for updates
    update.check(function (err, status) {
      if (err || !status) {
        if (showAlert) {
          dialog.showMessageBox({
            type: 'info',
            buttons: ['Close'],
            title: 'No update available',
            message: 'You are currently running the latest version of Gitify.'
          });
        }

        if (isDarwin) {
          mb.app.dock.hide();
        }
      }

      if (!err && status) {
        update.download();
      }
    });
  }

  function confirmAutoUpdate (quitAndUpdate) {
    dialog.showMessageBox({
      type: 'question',
      buttons: ['Update & Restart', 'Cancel'],
      title: 'Update Available',
      cancelId: 99,
      message: 'There is an update available. Would you like to update Gitify now?'
    }, function (response) {
      console.log('Exit: ' + response);
      if (isDarwin) {
        mb.app.dock.hide();
      }

      if (response === 0) {
        quitAndUpdate();
      }
    });
  }

  ipc.on('reopen-window', function () {
    mb.window.show();
  });

  ipc.on('update-icon', function (event, arg) {
    if (arg === 'TrayActive') {
      mb.tray.setImage(iconActive);
    } else {
      mb.tray.setImage(iconIdle);
    }
  });

  ipc.on('startup-enable', function () {
    if (!isLinux) {
      autoStart.enable();
    }
  });

  ipc.on('startup-disable', function () {
    if (!isLinux) {
      autoStart.disable();
    }
  });

  ipc.on('check-update', function () {
    checkAutoUpdate(true);
  });

  ipc.on('app-quit', function () {
    mb.app.quit();
  });

  mb.tray.setToolTip('GitHub Notifications on your menu bar.');
});
<|endoftext|>


<commit_before>var mongoose = require('mongoose');
var feedparser = require('feedparser')
var request = require('request');

var feedSchema = mongoose.Schema({
    _id:              { type: String, required: true, unique: true },
    title:            String,
    description:      String,
    link:             String,
    xmlUrl:           String,
    date:             { type: Date, default: Date.now },
    pubDate:          { type: Date, default: Date.now },
    author:           String,
    language:         String,
    image:            { title: String, url: String },
    favicon:          String,
    copyright:        String,
    generator:        String,
    categories:       [String]
});

feedSchema.virtual('url').get(function () {
  return this._id;
});

feedSchema.virtual('url').set(function (url) {
  this._id = url;
});

var Feed = mongoose.model('Feed', feedSchema);

var articleSchema = mongoose.Schema({
    title:            String,
    description:      String,
    link:             String,
    origLink:         String,
    date:             { type: Date, default: Date.now },
    pubDate:          { type: Date, default: Date.now },
    author:           String,
    guid:             String,
    comments:         String,
    image:            { title: String, url: String },
    categories:       [String],
    source:           { title: String, url: String },
    enclosures:       [{ url: String, type: String, length: String }],
    feed:             { type: String, ref: 'Feed' },
});

var Article = mongoose.model('Article', articleSchema);

function connect(uri, database, port) {
    port = typeof port !== 'undefined' ? port : 27017;
    mongoose.connect(uri, database, port);

    mongoose.connection.on('error', function(e){
        console.error("Could not connect to MongoDB: "+e.message);
        process.exit(1);
    });

    mongoose.connection.once('open', function callback () {
        console.log("Connection to MongoDB was successful.");
    });
}

function addFeed(url) {
    Feed.count({ url: url }, function(error, count) {
        if(error != null) {
            console.error('Failed to check if feed exists in MongoDB: '+error);
        }
        else {
            if(count == 0) {
               requestAndParseFeed(url);
            }
            else if(count == 1) {
                console.log('Feed '+url+' already exists in the MongoDB. '
                + 'Skipping database write.');
            }
            else {
                console.error('Multiple documents with same url exist in '
                + 'MongoDB. This should not happen!');
            }
        }
    });
}

function requestAndParseFeed(url) {
    request(createRequest(url), function(error, response, body)
        { handleResponse(url, error, response, body) });
}

function createRequest(url) {
    var request = { uri: url };
    return request;
}

function handleResponse(url, error, response, body) {
    if(error != null) {
        console.error('error: '+error);
    }
    else if (response.statusCode == 200) {
        feedparser.parseString(body)
        .on('meta', function(meta) { saveOrUpdateFeedMeta(meta, url) })
        .on('article', function(article) { saveOrUpdateArticle(article, url) })
        .on('error', function(error) { handleParseError(error, url) });
    }
    else if (response.statusCode == 304) {
        console.log('Feed '+url+' not modified (304). Skipping parsing.' );
    }
    else {
        console.warn('HTTP status code received that can not be handled by '
            + 'this module: '+response.statusCode);
    }
}

function handleParseError(error, url) {
    console.error('Could not parse feed at '+url+'. '+error);
}

function saveOrUpdateFeedMeta(meta, url) {
    Feed.findOne({ _id: url }, function(error, feedDocument) {
        if(error != null) {
            console.error('Failed to get feed from MongoDB: '+error);
        }
        else {
            if(feedDocument == null) {
                saveFeedMeta(meta, url);
            }
            else {
                updateFeedMeta(feedDocument, meta, url);
            }
        }
    });
}

function saveFeedMeta(meta, url) {
    var feedDocument = createFeedDocument(meta, url);

    feedDocument.save(function (error, feedDocument) {
        if(error != null) {
            console.error('Failed to save feed meta to MongoDB: '+error);
        }
        else {
            console.log('Added new feed "'+feedDocument.url+'" to MongoDB.');
        }
    });
}

function updateFeedMeta(feedDocument, meta) {
    if(!feedEqualsWithMeta(feedDocument, meta)) {
        feedDocument.title = meta.title;
        feedDocument.description = meta.description;
        feedDocument.link = meta.link;
        feedDocument.xmlUrl = meta.xmlUrl;
        feedDocument.date = meta.date;
        feedDocument.pubDate = meta.pubDate;
        feedDocument.author = meta.author;
        feedDocument.language = meta.language;
        feedDocument.image = meta.image;
        feedDocument.favicon = meta.favicon;
        feedDocument.copyright = meta.copyright;
        feedDocument.generator = meta.generator;
        feedDocument.categories = meta.categories;

        feedDocument.save(function (error, feedDocument) {
            if(error != null) {
                console.error('Failed to update feed meta to MongoDB: '+error);
            }
            else {
                console.log('Updated feed "'+feedDocument.url+'" in MongoDB.');
            }
        });
    }
}

function feedEqualsWithMeta(feedDocument, meta) {
    var equals = false;

    if(feedDocument.title == meta.title &&
        feedDocument.description == meta.description &&
        feedDocument.link == meta.link &&
        feedDocument.xmlUrl == meta.xmlUrl &&
        feedDocument.date == meta.date &&
        feedDocument.pubDate == meta.pubDate &&
        feedDocument.author == meta.author &&
        feedDocument.language == meta.language &&
        feedDocument.image.title == meta.image.title &&
        feedDocument.image.url == meta.image.url &&
        feedDocument.favicon == meta.favicon &&
        feedDocument.copyright == meta.copyright &&
        feedDocument.generator == meta.generator &&
        JSON.stringify(feedDocument.categories) ==
            JSON.stringify(meta.categories)) {
        equals = true;
    }

    return equals;
}

function createFeedDocument(meta, url) {
    return new Feed({ url: url, title: meta.title,
        description: meta.description, link: meta.link, xmlUrl: meta.xmlUrl,
        date: meta.date, pubDate: meta.pubDate, author: meta.author,
        language: meta.language, image: meta.image, favicon: meta.favicon,
        copyright: meta.copyright, generator: meta.generator,
        categories: meta.categories });
}

function saveOrUpdateArticle(article, url) {
    Article.findOne({ guid: article.guid }, function(error, articleDocument) {
        if(error != null) {
            console.error('Failed to get article from MongoDB: '+error);
        }
        else {
            if(articleDocument == null) {
                saveArticle(article, url);
            }
            else {
                updateArticle(articleDocument, article, url);
            }
        }
    });
}

function saveArticle(article, url) {
    var articleDocument = createArticleDocument(article, url);

    articleDocument.save(function (error, articleDocument) {
        if(error != null) {
            console.error('Failed to save article to MongoDB: '+error);
        }
        else {
            console.log('Added new article "'+articleDocument.guid
            + '" to MongoDB');
        }
    });
}

function updateArticle(articleDocument, article) {
    console.log('Should update article, but not yet implemented.');
}

function createArticleDocument(article, url) {
    return new Article({ title: article.title,
        description: article.description, link: article.link,
        origLink: article.origLink, guid: article.guid,
        comments: article.comments, image: article.image,
        categories: article.categories, source: article.source,
        enclosures: article.enclosures, feed: url });
}

function updateDatabase() {
    Feed.find(function(error, feedDocuments) {
        if(error != null) {
            console.error('Failed to get feeds from MongoDB: '+error);
        }
        else {
            feedDocuments.forEach(function(feedDocument) {
                console.log('Updating feed '+feedDocument.url);
                requestAndParseFeed(feedDocument.url);
            });
        }
    });
}

exports.connect = connect;
exports.addFeed = addFeed;
exports.updateDatabase = updateDatabase;
<commit_msg>Made comparing existing article to new one more robust by including parent feed url in addition to guid to comparing.<commit_after>var mongoose = require('mongoose');
var feedparser = require('feedparser')
var request = require('request');

var feedSchema = mongoose.Schema({
    _id:              { type: String, required: true, unique: true },
    title:            String,
    description:      String,
    link:             String,
    xmlUrl:           String,
    date:             { type: Date, default: Date.now },
    pubDate:          { type: Date, default: Date.now },
    author:           String,
    language:         String,
    image:            { title: String, url: String },
    favicon:          String,
    copyright:        String,
    generator:        String,
    categories:       [String]
});

feedSchema.virtual('url').get(function () {
  return this._id;
});

feedSchema.virtual('url').set(function (url) {
  this._id = url;
});

var Feed = mongoose.model('Feed', feedSchema);

var articleSchema = mongoose.Schema({
    title:            String,
    description:      String,
    link:             String,
    origLink:         String,
    date:             { type: Date, default: Date.now },
    pubDate:          { type: Date, default: Date.now },
    author:           String,
    guid:             String,
    comments:         String,
    image:            { title: String, url: String },
    categories:       [String],
    source:           { title: String, url: String },
    enclosures:       [{ url: String, type: String, length: String }],
    feed:             { type: String, ref: 'Feed' },
});

var Article = mongoose.model('Article', articleSchema);

function connect(uri, database, port) {
    port = typeof port !== 'undefined' ? port : 27017;
    mongoose.connect(uri, database, port);

    mongoose.connection.on('error', function(e){
        console.error("Could not connect to MongoDB: "+e.message);
        process.exit(1);
    });

    mongoose.connection.once('open', function callback () {
        console.log("Connection to MongoDB was successful.");
    });
}

function addFeed(url) {
    Feed.count({ url: url }, function(error, count) {
        if(error != null) {
            console.error('Failed to check if feed exists in MongoDB: '+error);
        }
        else {
            if(count == 0) {
               requestAndParseFeed(url);
            }
            else if(count == 1) {
                console.log('Feed '+url+' already exists in the MongoDB. '
                + 'Skipping database write.');
            }
            else {
                console.error('Multiple documents with same url exist in '
                + 'MongoDB. This should not happen!');
            }
        }
    });
}

function requestAndParseFeed(url) {
    request(createRequest(url), function(error, response, body)
        { handleResponse(url, error, response, body) });
}

function createRequest(url) {
    var request = { uri: url };
    return request;
}

function handleResponse(url, error, response, body) {
    if(error != null) {
        console.error('error: '+error);
    }
    else if (response.statusCode == 200) {
        feedparser.parseString(body)
        .on('meta', function(meta) { saveOrUpdateFeedMeta(meta, url) })
        .on('article', function(article) { saveOrUpdateArticle(article, url) })
        .on('error', function(error) { handleParseError(error, url) });
    }
    else if (response.statusCode == 304) {
        console.log('Feed '+url+' not modified (304). Skipping parsing.' );
    }
    else {
        console.warn('HTTP status code received that can not be handled by '
            + 'this module: '+response.statusCode);
    }
}

function handleParseError(error, url) {
    console.error('Could not parse feed at '+url+'. '+error);
}

function saveOrUpdateFeedMeta(meta, url) {
    Feed.findOne({ _id: url }, function(error, feedDocument) {
        if(error != null) {
            console.error('Failed to get feed from MongoDB: '+error);
        }
        else {
            if(feedDocument == null) {
                saveFeedMeta(meta, url);
            }
            else {
                updateFeedMeta(feedDocument, meta, url);
            }
        }
    });
}

function saveFeedMeta(meta, url) {
    var feedDocument = createFeedDocument(meta, url);

    feedDocument.save(function (error, feedDocument) {
        if(error != null) {
            console.error('Failed to save feed meta to MongoDB: '+error);
        }
        else {
            console.log('Added new feed "'+feedDocument.url+'" to MongoDB.');
        }
    });
}

function updateFeedMeta(feedDocument, meta) {
    if(!feedEqualsWithMeta(feedDocument, meta)) {
        feedDocument.title = meta.title;
        feedDocument.description = meta.description;
        feedDocument.link = meta.link;
        feedDocument.xmlUrl = meta.xmlUrl;
        feedDocument.date = meta.date;
        feedDocument.pubDate = meta.pubDate;
        feedDocument.author = meta.author;
        feedDocument.language = meta.language;
        feedDocument.image = meta.image;
        feedDocument.favicon = meta.favicon;
        feedDocument.copyright = meta.copyright;
        feedDocument.generator = meta.generator;
        feedDocument.categories = meta.categories;

        feedDocument.save(function (error, feedDocument) {
            if(error != null) {
                console.error('Failed to update feed meta to MongoDB: '+error);
            }
            else {
                console.log('Updated feed "'+feedDocument.url+'" in MongoDB.');
            }
        });
    }
}

function feedEqualsWithMeta(feedDocument, meta) {
    var equals = false;

    if(feedDocument.title == meta.title &&
        feedDocument.description == meta.description &&
        feedDocument.link == meta.link &&
        feedDocument.xmlUrl == meta.xmlUrl &&
        feedDocument.date == meta.date &&
        feedDocument.pubDate == meta.pubDate &&
        feedDocument.author == meta.author &&
        feedDocument.language == meta.language &&
        feedDocument.image.title == meta.image.title &&
        feedDocument.image.url == meta.image.url &&
        feedDocument.favicon == meta.favicon &&
        feedDocument.copyright == meta.copyright &&
        feedDocument.generator == meta.generator &&
        JSON.stringify(feedDocument.categories) ==
            JSON.stringify(meta.categories)) {
        equals = true;
    }

    return equals;
}

function createFeedDocument(meta, url) {
    return new Feed({ url: url, title: meta.title,
        description: meta.description, link: meta.link, xmlUrl: meta.xmlUrl,
        date: meta.date, pubDate: meta.pubDate, author: meta.author,
        language: meta.language, image: meta.image, favicon: meta.favicon,
        copyright: meta.copyright, generator: meta.generator,
        categories: meta.categories });
}

function saveOrUpdateArticle(article, url) {
    Article.findOne({ guid: article.guid, feed: url }, function(error, articleDocument) {
        if(error != null) {
            console.error('Failed to get article from MongoDB: '+error);
        }
        else {
            if(articleDocument == null) {
                saveArticle(article, url);
            }
            else {
                updateArticle(articleDocument, article, url);
            }
        }
    });
}

function saveArticle(article, url) {
    var articleDocument = createArticleDocument(article, url);

    articleDocument.save(function (error, articleDocument) {
        if(error != null) {
            console.error('Failed to save article to MongoDB: '+error);
        }
        else {
            console.log('Added new article "'+articleDocument.guid
            + '" to MongoDB');
        }
    });
}

function updateArticle(articleDocument, article) {
    console.log('Should update article, but not yet implemented.');
}

function createArticleDocument(article, url) {
    return new Article({ title: article.title,
        description: article.description, link: article.link,
        origLink: article.origLink, guid: article.guid,
        comments: article.comments, image: article.image,
        categories: article.categories, source: article.source,
        enclosures: article.enclosures, feed: url });
}

function updateDatabase() {
    Feed.find(function(error, feedDocuments) {
        if(error != null) {
            console.error('Failed to get feeds from MongoDB: '+error);
        }
        else {
            feedDocuments.forEach(function(feedDocument) {
                console.log('Updating feed '+feedDocument.url);
                requestAndParseFeed(feedDocument.url);
            });
        }
    });
}

exports.connect = connect;
exports.addFeed = addFeed;
exports.updateDatabase = updateDatabase;
<|endoftext|>


<commit_before>var request = require("request");
var fs = require("fs");

    // Parameters
        // TODO : Prendre groupe de tutorat en parametre
        // TODO : prendre en parametre si on enleve les multi-day events
        // TODO : CIP en parametre

    // TODO : Si pas de groupe de tutorat, ne pas masquer tutorat
    // TODO : Enleve tutorat inutile (Faire le check a la creation de l'objet JSON ? ou apres?)
    // TODO : enleve multi-day events
    // TODO : Polling 3-4 fois par jour durant heures ouvrables (dison entre 5h du matin & 11h le soir) pour voir si ya du changement dans le ical (Garder une copie de la string recu pour comparaison rapide ?)
    // TODO : Reconstruire ical
    // TODO : Http server pour repondre a la requete (On devrais effacer les events inutile a ce moment puisque c'est la qu'on recoit les parametres
    // TODO : Handle les infos du calendrier
    // TODO : S'assurer de bien catcher les exceptions, le service ne doit pas crasher

request.get("http://www.gel.usherbrooke.ca/horarius/ical?cip=abdj2702", function(error, response, body){
if (!error) {
    var calendarInfos = body.substring(0,body.indexOf("BEGIN:VEVENT"))
    var events = body.substring(body.indexOf("BEGIN:VEVENT"),body.length);

    events = events.split(/\r\nBEGIN:.*\r\n/g);

    var eventList = parseEvents(events);

    console.log(eventList[50]["LOCATION"]);
}else{
    console.log(error);
}
});

// TODO : Separate in helper file ?
function parseEvents(events){
    var eventList = [];
    var json = {};
    var eventLines;
    var keyAndValue;

    for(var j=0;j<events.length;j++){
        eventLines = events[j].split("\r\n");
        for(var i=0;i<eventLines.length;i++){
            keyAndValue = eventLines[i].split(":");
            json[keyAndValue[0]] = keyAndValue[1];
        }
        eventList.push(json);
        json = {};
    }

    return eventList;
}

function writeEvents(eventList){
    // TODO : Use async writing ?
    var fileContent = "";
    fs.writeFileSync("/tmp/test", fileContent, function(err) {
    if(err) {
        return console.log(err);
    }

    console.log("The file was saved!");
});
}<commit_msg>+ Trimmed events<commit_after>var request = require("request");
var fs = require("fs");

    // Parameters
        // TODO : Prendre groupe de tutorat en parametre
        // TODO : prendre en parametre si on enleve les multi-day events
        // TODO : CIP en parametre

    // TODO : Add HTTPS so user can send their client secret in the request

    // TODO : Si pas de groupe de tutorat, ne pas masquer tutorat
    // TODO : Enleve tutorat inutile (Faire le check a la creation de l'objet JSON ? ou apres?)
    // TODO : enleve multi-day events
    // TODO : Polling 3-4 fois par jour durant heures ouvrables (dison entre 5h du matin & 11h le soir) pour voir si ya du changement dans le ical (Garder une copie de la string recu pour comparaison rapide ?)
    // TODO : Reconstruire ical
    // TODO : Http server pour repondre a la requete (On devrais effacer les events inutile a ce moment puisque c'est la qu'on recoit les parametres
    // TODO : Handle les infos du calendrier
    // TODO : S'assurer de bien catcher les exceptions, le service ne doit pas crasher

request.get("http://www.gel.usherbrooke.ca/horarius/ical?cip=abdj2702", function(error, response, body){
if (!error) {

    var parsedBody = parseResponse(body);
    //parsedBody.calendarInfos

    var eventList = parseEvents(parsedBody.events);
    writeEvents(eventList);

    //console.log(eventList[50]["LOCATION"]);
}else{
    console.log(error);
}
});

// TODO : Separate in helper file ?

function parseResponse(body){
    var calendarInfos = body.substring(0,body.indexOf("BEGIN:VEVENT"))
    var events = body.substring(body.indexOf("\r\nBEGIN:VEVENT"),body.length);

    return {"calendarInfos" : calendarInfos, "events":events.split(/\r\nBEGIN:.*\r\n/g)};
}
function parseEvents(events){
    var eventList = [];
    var json = {};
    var eventLines;
    var keyAndValue;

    for(var j=0;j<events.length;j++){
        eventLines = events[j].split("\r\n");
        console.log("Event "+j);
        for(var i=0;i<eventLines.length;i++){
            console.log("Event Line : "+i);
            keyAndValue = eventLines[i].split(":");
            if(keyAndValue[0] != "END" && keyAndValue[0] != "" && keyAndValue[0] != undefined && keyAndValue[1] != undefined){            // We don't want the end line into the parsed object
                json[keyAndValue[0]] = keyAndValue[1];
            }
        }
        console.log(json);
        if(Object.keys(json).length > 0){
            eventList.push(json);
            console.log("PUSHED !");
        }
        json = {};
    }

    return eventList;
}

function writeEvents(eventList){
    // TODO : Use async writing ?
    var fileContent = "";
    fileContent = JSON.stringify(eventList);
    fs.writeFile("test.output", fileContent, function(err){
        if(err){
            console.log(err);
        }else{
            console.log("The file was saved!");
        }
    });
}<|endoftext|>


<commit_before>(function($, game, Field) {

    var $board = $("#game-board");
    var board = $board.get(0);
    var x;
    var rowsToFetch = 10;

    var onBottomScroll = function() {
        var bottomHex = $(".hex:first");
        var currentColCount = game.GUI.grid.state.rows[0].length;
        board.scrollTop -= bottomHex.height() * (rowsToFetch - 1);

        var rows = game.GUI.grid.state.rows;
        var ordinate = {
            x1 : rows[rows.length-1][0].position.x+1,
            y1 : rows[rows.length-1][0].position.y
        };
        ordinate.x2 = ordinate.x1 + rowsToFetch;
        ordinate.y2 = ordinate.y1 + rows[rows.length-1].length;
debugger;
        getMockupFieldData(ordinate, function(rows) {
debugger;
            for (var r = 0; r < rows.length; r++) {
                game.GUI.grid.state.rows.shift();
                game.GUI.grid.state.rows.push(rows[r]);
            }
            game.GUI.grid.setState({rows: game.GUI.grid.state.rows});
        });
    };

    var onTopScroll = function() {
        var bottomHex = $(".hex:first");
        var currentColCount = game.GUI.grid.state.rows[0].length;
        board.scrollTop += bottomHex.height() * (rowsToFetch - 1);

        x = game.GUI.grid.state.rows[0][0].position.x;
        for (var i = 0; i < rowsToFetch; i++) {
            x--;
            prependRow(currentColCount, true);
        }
        game.GUI.grid.setState({rows: game.GUI.grid.state.rows});
    };

    var onScroll = function (event) {
        var trueDivHeight = board.scrollHeight;
        var divHeight = $board.height();
        var maxScollTop = trueDivHeight - divHeight;
        if (board.scrollTop === maxScollTop){
            onBottomScroll();
        }
        if (board.scrollTop === 0){
            onTopScroll();
        }
    };

    var prependRow = function(colCount, magic, currentData) {
        var result = currentData;
        if (!currentData){
            result = game.GUI.grid.state.rows;
        }
        if (magic){
           result.pop();
        }
        var row = [];
        var y = game.GUI.grid.state.rows[0][0].position.y;
        for (var i = 0; i < colCount; i++) {
          var fieldParms = {
            position : {
                x:x,
                y:y
            }
          };
          row.push(new Field(fieldParms));
          y--;
        }
        result.unshift(row);
        return result;
    };

    var getMockupFieldData = function  (ordinate, onComplete) {
        var rows = [];

        for (var x = ordinate.x1; x < ordinate.x2; x++) {
            var row = [];
            for (var y = ordinate.y1; y < ordinate.y2; y++) {
              var fieldParms = {
                position : {
                    x : x,
                    y : y
                }
              };
              row.push(new Field(fieldParms));
            }
            rows.push(row);
        }

        window.setTimeout((function() {
            onComplete(rows);
        }), 3000);
    };

    var $loading = $('

');
    $loading.insertAfter($board);
    var reload = function(){
        $board.hide();
        $loading.show();
        board.removeEventListener('scroll', onScroll);
        var needed = game.GUI.board.neededHexTilesToOverfillScreen();
        var viewPoint = {
            x:-0,y:-0
        };

        var ordinate = {
            x1 : Math.round(viewPoint.x - (needed.rowCount/2)),
            x2 : Math.round(viewPoint.x + (needed.rowCount/2)),
            y1 : Math.round(viewPoint.y - (needed.colCount/2)),
            y2 : Math.round(viewPoint.y + (needed.colCount/2))
        };

        getMockupFieldData(ordinate, function(mockupFieldData) {
            game.GUI.board.load(mockupFieldData, function() {
                    board.addEventListener('scroll', onScroll);
            });
        });
    };

    $("body").on("game-components-ready",reload);
    $(window).resize(reload);

})(window.jQuery, window.game, window.game.classes.Field);<commit_msg>fixed early scroll top setup<commit_after>(function($, game, Field) {

    var $board = $("#game-board");
    var board = $board.get(0);
    var x;
    var rowsToFetch = 10;

    var onBottomScroll = function() {
        board.removeEventListener('scroll', onScroll);
        var bottomHex = $(".hex:first");
        var currentColCount = game.GUI.grid.state.rows[0].length;

        var rows = game.GUI.grid.state.rows;
        var ordinate = {
            x1 : rows[rows.length-1][0].position.x+1,
            y1 : rows[rows.length-1][0].position.y
        };
        ordinate.x2 = ordinate.x1 + rowsToFetch;
        ordinate.y2 = ordinate.y1 + rows[rows.length-1].length;
        getMockupFieldData(ordinate, function(rows) {
            for (var r = 0; r < rows.length; r++) {
                game.GUI.grid.state.rows.shift();
                game.GUI.grid.state.rows.push(rows[r]);
            }
            board.scrollTop -= bottomHex.height() * (rowsToFetch - 1);
            game.GUI.grid.setState({rows: game.GUI.grid.state.rows}, function() {
                board.addEventListener('scroll', onScroll);
            });
        });
    };

    var onTopScroll = function() {
        var bottomHex = $(".hex:first");
        var currentColCount = game.GUI.grid.state.rows[0].length;
        board.scrollTop += bottomHex.height() * (rowsToFetch - 1);

        x = game.GUI.grid.state.rows[0][0].position.x;
        for (var i = 0; i < rowsToFetch; i++) {
            x--;
            prependRow(currentColCount, true);
        }
        game.GUI.grid.setState({rows: game.GUI.grid.state.rows});
    };

    var onScroll = function (event) {
        var trueDivHeight = board.scrollHeight;
        var divHeight = $board.height();
        var maxScollTop = trueDivHeight - divHeight;
        if (board.scrollTop === maxScollTop){
            onBottomScroll();
        }
        if (board.scrollTop === 0){
            onTopScroll();
        }
    };

    var prependRow = function(colCount, magic, currentData) {
        var result = currentData;
        if (!currentData){
            result = game.GUI.grid.state.rows;
        }
        if (magic){
           result.pop();
        }
        var row = [];
        var y = game.GUI.grid.state.rows[0][0].position.y;
        for (var i = 0; i < colCount; i++) {
          var fieldParms = {
            position : {
                x:x,
                y:y
            }
          };
          row.push(new Field(fieldParms));
          y--;
        }
        result.unshift(row);
        return result;
    };

    var getMockupFieldData = function  (ordinate, onComplete) {
        var rows = [];

        for (var x = ordinate.x1; x < ordinate.x2; x++) {
            var row = [];
            for (var y = ordinate.y1; y < ordinate.y2; y++) {
              var fieldParms = {
                position : {
                    x : x,
                    y : y
                }
              };
              row.push(new Field(fieldParms));
            }
            rows.push(row);
        }

        window.setTimeout((function() {
            onComplete(rows);
        }), 3000);
    };

    var $loading = $('

');
    $loading.insertAfter($board);
    var reload = function(){
        $board.hide();
        $loading.show();
        board.removeEventListener('scroll', onScroll);
        var needed = game.GUI.board.neededHexTilesToOverfillScreen();
        var viewPoint = {
            x:-0,y:-0
        };

        var ordinate = {
            x1 : Math.round(viewPoint.x - (needed.rowCount/2)),
            x2 : Math.round(viewPoint.x + (needed.rowCount/2)),
            y1 : Math.round(viewPoint.y - (needed.colCount/2)),
            y2 : Math.round(viewPoint.y + (needed.colCount/2))
        };

        getMockupFieldData(ordinate, function(mockupFieldData) {
            game.GUI.board.load(mockupFieldData, function() {
                    board.addEventListener('scroll', onScroll);
            });
        });
    };

    $("body").on("game-components-ready",reload);
    $(window).resize(reload);

})(window.jQuery, window.game, window.game.classes.Field);<|endoftext|>