<commit_before>import {Color, Vector2} from 'flockn/types';
import serializable from 'flockn/mixins/serializable';

class TextureImage {
  constructor(texture) {
    // The default values for `image`
    this.color = Color.transparent();
    this.drawable = false;
    this.offset = new Vector2(0, 0);
    this.data = null;
    this.width = 0;
    this.height = 0;

    var filename = '';

    Object.defineProperty(this, 'filename', {
      get: function () {
        return filename;
      },
      set: function (value) {
        filename = value;

        // TODO: Most of this should already be handled by the preloader
        var img = new Image();
        img.src = filename;

        img.onload = () => {
          this.data = img;
          this.width = img.width;
          this.height = img.height;
          this.drawable = true;

          texture.trigger('image-loaded');
        };
      },
      enumerable: true
    });
  }

  toJSON() {
    return serialize.toJSON(this);
  }

  toString() {
    return serialize.toString(this);
  }
}

serializable(TextureImage);

export default TextureImage;
<commit_msg>:fire: Update texture image dependencies<commit_after>import {Color, Vector2} from '../types';
import serializable from '../mixins/serializable';

class TextureImage {
  constructor(texture) {
    // The default values for `image`
    this.color = Color.transparent();
    this.drawable = false;
    this.offset = new Vector2(0, 0);
    this.data = null;
    this.width = 0;
    this.height = 0;

    var filename = '';

    Object.defineProperty(this, 'filename', {
      get: function () {
        return filename;
      },
      set: function (value) {
        filename = value;

        // TODO: Most of this should already be handled by the preloader
        var img = new Image();
        img.src = filename;

        img.onload = () => {
          this.data = img;
          this.width = img.width;
          this.height = img.height;
          this.drawable = true;

          texture.trigger('image-loaded');
        };
      },
      enumerable: true
    });
  }

  toJSON() {
    return serialize.toJSON(this);
  }

  toString() {
    return serialize.toString(this);
  }
}

serializable(TextureImage);

export default TextureImage;
<|endoftext|>


<commit_before>import window from 'global/window'

const {HTMLVideoElement} = window
const {HTMLCanvasElement} = window
const {HTMLImageElement} = window

// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
const {
  HAVE_NOTHING = 0,
  HAVE_METADATA = 1,
  HAVE_CURRENT_DATA = 2,
  HAVE_FUTURE_DATA = 3,
  HAVE_ENOUGH_DATA = 4,
} = (HTMLVideoElement || {})

export const isCanvas = (d) => d instanceof HTMLCanvasElement
export const isVideo = (d) => d instanceof HTMLVideoElement
export const isImage = (d) => d instanceof HTMLImageElement

export function isTextureDataReady(data) {
  const resolution = getTextureDataResolution(data)
  if (!resolution[0] || !resolution[1]) { return false }
  if (isVideo(data) && data.readyState >= HAVE_CURRENT_DATA) {
    return true
  } else if (isImage(data) || isCanvas(data)) {
    if (data.width && data.height) {
      return true
    }
  }
  return false
}

export function getTextureDataResolution(data) {
  if (isImage(data) || isCanvas(data)) {
    return [data.width, data.height]
  } else if (isVideo(data)) {
    return [data.videoWidth || 0, data.videoHeight || 0]
  } else if (data && data.shape) {
    return data.shape
  } else {
    return [0, 0]
  }
}

export function isCubeTextureDataReady(data) {
  if (isVideo(data) && data.readyState >= HAVE_CURRENT_DATA) {
    return true
  } else if (isImage(data) || isCanvas(data)) {
    if (data.width && data.height) {
      return true
    }
  }
  return false
}

export function getCubeTextureDataResolution(data) {
  if (Array.isArray(data)) {
    data = data
      .filter((d) => d)
      .filter((d) => isImage(d) || isVideo(d) || d.shape.every(Boolean))
      [0]
    return getCubeTextureDataResolution(data)
  }
  if (isImage(data) || isCanvas(data)) {
    return [data.width, data.height]
  } else if (isVideo(data)) {
    return [data.videoWidth || 0, data.videoHeight || 0]
  } else if (data && data.shape) {
    return data.shape
  } else {
    return [0, 0]
  }
}
<commit_msg>refactor(src/texture/utils): Ensure video has frames<commit_after>import window from 'global/window'

const {HTMLVideoElement} = window
const {HTMLCanvasElement} = window
const {HTMLImageElement} = window

// https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/readyState
const {
  HAVE_NOTHING = 0,
  HAVE_METADATA = 1,
  HAVE_CURRENT_DATA = 2,
  HAVE_FUTURE_DATA = 3,
  HAVE_ENOUGH_DATA = 4,
} = (HTMLVideoElement || {})

export const isCanvas = (d) => d instanceof HTMLCanvasElement
export const isVideo = (d) => d instanceof HTMLVideoElement
export const isImage = (d) => d instanceof HTMLImageElement

export function isTextureDataReady(data) {
  const resolution = getTextureDataResolution(data)
  if (!resolution[0] || !resolution[1]) { return false }
  if (isVideo(data) && data.readyState > HAVE_CURRENT_DATA) {
    return true
  } else if (isImage(data) || isCanvas(data)) {
    if (data.width && data.height) {
      return true
    }
  }
  return false
}

export function getTextureDataResolution(data) {
  if (isImage(data) || isCanvas(data)) {
    return [data.width, data.height]
  } else if (isVideo(data)) {
    return [data.videoWidth || 0, data.videoHeight || 0]
  } else if (data && data.shape) {
    return data.shape
  } else {
    return [0, 0]
  }
}

export function isCubeTextureDataReady(data) {
  if (isVideo(data) && data.readyState > HAVE_CURRENT_DATA) {
    return true
  } else if (isImage(data) || isCanvas(data)) {
    if (data.width && data.height) {
      return true
    }
  }
  return false
}

export function getCubeTextureDataResolution(data) {
  if (Array.isArray(data)) {
    data = data
      .filter((d) => d)
      .filter((d) => isImage(d) || isVideo(d) || d.shape.every(Boolean))
      [0]
    return getCubeTextureDataResolution(data)
  }
  if (isImage(data) || isCanvas(data)) {
    return [data.width, data.height]
  } else if (isVideo(data)) {
    return [data.videoWidth || 0, data.videoHeight || 0]
  } else if (data && data.shape) {
    return data.shape
  } else {
    return [0, 0]
  }
}
<|endoftext|>


<commit_before>const fs = require('fs');
const path = require('path');
const Table = require('ascii-table');
const winston = require('winston');

// load all the command handlers
let commandHandlers = [];
const commandHandlerLoadPath = path.resolve(process.cwd(),
  './command_handlers');
winston.log('debug', 'Loading commands from %s', commandHandlerLoadPath);
fs.readdir(commandHandlerLoadPath, function(err, files) {
  files.forEach(function(file) {
    if (file.match(/^.+\.js$/)) {
      const commHandler = require(path.resolve(commandHandlerLoadPath, file));
      if (
        typeof commHandler === 'object' &&
        commHandler.bind && typeof commHandler.bind === 'string' &&
        commHandler.handler && typeof commHandler.handler === 'function'
      ) {
        winston.log('info', 'Registered command %s from file %s',
          commHandler.bind, file);
        commandHandlers.push(commHandler);
      }
    }
  });
});

// special help command
commandHandlers.push({
  bind: 'help',
  handler: function(message) {
    const table = new Table();
    table.setHeading('Command', 'Help');
    table.setTitle('Help for ciarancrocker/sgs_bot');
    commandHandlers.forEach(function(handler) {
      if (handler.help) {
        table.addRow(handler.bind, handler.help);
      } else {
        table.addRow(handler.bind, 'No help provided');
      }
    });
    message.reply(table.toString(), {code: true});
  },
  help: 'This command, you donut.',
});

module.exports.dispatchMessage = function(message) {
  // filter out messages that aren't commands for us
  if (message.content[0] != process.env.COMMAND_PREFIX) return;

  // filter to target handlers
  const targetCommand = message.content.slice(1).split(' ')[0];
  const possibleHandlers =
    commandHandlers.filter((handler) => handler.bind == targetCommand);

  if (possibleHandlers.length == 0) { // command not found
    winston.log('info', 'Command %s from user %s not found', targetCommand,
      message.author.tag);
    return;
  }
  const handler = possibleHandlers[0];

  // validate permissions if the command is for administrators only
  if (handler.administrative) {
    if (!message.member) {
      // needs to be run from a server
      winston.log('info', 'Denied user %s access to command %s',
        message.author.tag, targetCommand);
      message.reply('fuck off');
      return;
    }
    const memberRoles = message.member.roles.array();
    if (memberRoles.filter((role) => role.id == process.env.ADMIN_ROLE)
      .length == 0) {
      message.member.send('fuck off');
      winston.log('info', 'Denied user %s access to command %s',
        message.author.tag, targetCommand);
      return;
    }
  }

  // dispatch message to designated handler
  winston.log('info', 'Dispatched command %s for user %s', targetCommand,
    message.author.tag);
  possibleHandlers[0].handler(message);
};

<commit_msg>i am bad at code conventions<commit_after>const fs = require('fs');
const path = require('path');
const Table = require('ascii-table');
const winston = require('winston');

// load all the command handlers
let commandHandlers = [];
const commandHandlerLoadPath = path.resolve(process.cwd(),
  './command_handlers');
winston.log('debug', 'Loading commands from %s', commandHandlerLoadPath);
fs.readdir(commandHandlerLoadPath, function(err, files) {
  files.forEach(function(file) {
    if (file.match(/^.+\.js$/)) {
      const commHandler = require(path.resolve(commandHandlerLoadPath, file));
      if (
        typeof commHandler === 'object' &&
        commHandler.bind && typeof commHandler.bind === 'string' &&
        commHandler.handler && typeof commHandler.handler === 'function'
      ) {
        winston.log('info', 'Registered command %s from file %s',
          commHandler.bind, file);
        commandHandlers.push(commHandler);
      }
    }
  });
});

// special help command
commandHandlers.push({
  bind: 'help',
  handler: function(message) {
    const table = new Table();
    table.setHeading('Command', 'Help');
    table.setTitle('Help for ciarancrocker/sgs_bot');
    commandHandlers.forEach(function(handler) {
      if (handler.help) {
        table.addRow(handler.bind, handler.help);
      } else {
        table.addRow(handler.bind, 'No help provided');
      }
    });
    message.reply(table.toString(), {code: true});
  },
  help: 'This command, you donut.',
});

module.exports.dispatchMessage = function(message) {
  // filter out messages that aren't commands for us
  if (message.content[0] != process.env.COMMAND_PREFIX) return;

  // filter to target handlers
  const targetCommand = message.content.slice(1).split(' ')[0];
  const possibleHandlers =
    commandHandlers.filter((handler) => handler.bind == targetCommand);

  if (possibleHandlers.length == 0) { // command not found
    winston.log('info', 'Command %s from user %s not found', targetCommand,
      message.author.tag);
    return;
  }
  const handler = possibleHandlers[0];

  // validate permissions if the command is for administrators only
  if (handler.administrative) {
    if (!message.member) {
      // needs to be run from a server
      winston.log('info', 'Denied user %s access to command %s',
        message.author.tag, targetCommand);
      message.reply('fuck off');
      return;
    }
    const memberRoles = message.member.roles.array();
    if (memberRoles.filter((role) => role.id == process.env.ADMIN_ROLE)
      .length == 0) {
      message.member.send('fuck off');
      winston.log('info', 'Denied user %s access to command %s',
        message.author.tag, targetCommand);
      return;
    }
  }

  // dispatch message to designated handler
  winston.log('info', 'Dispatched command %s for user %s', targetCommand,
    message.author.tag);
  possibleHandlers[0].handler(message);
};

<|endoftext|>


<commit_before>// tests for all read methods
"use strict";
var fluid = require("infusion");
var namespace = "gpii.ctr.record.tests.read";
var read = fluid.registerNamespace(namespace);

var loader = require("../../../configs/lib/config-loader");
read.config = loader.loadConfig(require("../../../configs/express/test-pouch.json"));

var testUtils = require("../../tests/lib/testUtils")(read.config);

read.loadPouch = function() {
    read.pouch = require('../../tests/lib/pouch')(read.config);

    read.pouch.start(function() {
        read.startExpress();
    });
};

// Spin up an express instance
read.startExpress = function() {
    read.express = require('../../tests/lib/express')(read.config);

    read.express.start(function() {

        // Mount all variations on the module
        var record = require('../../record')(read.config);
        read.express.app.use('/record', record);

        // Add PouchDB with simulated CouchDb REST endpoints
        read.express.app.use('/pouch', require('express-pouchdb')(read.pouch.MemPouchDB));

        // Give express-pouch a few seconds to start up
        setTimeout(read.loadData, 2000);
    });
};

read.loadData = function() {
    read.pouch.loadData(read.runTests);
};

read.runTests = function() {
    var jqUnit = fluid.require("jqUnit");
    var request = require('request');
    jqUnit.module("Record API (read)");

    jqUnit.asyncTest("Test retrieving record by its uniqueID", function() {
        request.get("http://localhost:" + read.config.port + "/record/org.gnome.settings-daemon.peripherals.wacom.stylus.pressurecurve", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertEquals("The request should have been successful...", 200, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNotNull("There should be record data returned...", jsonData.record);

            if (jsonData.record) {
                testUtils.isSaneRecord(jqUnit, jsonData.record);
            }
        });
    });

    jqUnit.asyncTest("Test retrieving a record that does not exist", function() {
        request.get("http://localhost:" + read.config.port + "/record/totallyBogusFlibbertyGibbit", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertEquals("The request should returned a 404 (not found)...", 404, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNull("There should not be record data returned...", jsonData.record);
        });
    });

    jqUnit.asyncTest("Test retrieving a record that does not exist", function() {
        request.get("http://localhost:" + read.config.port + "/record/", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertNotEquals("The request should not be successful...", 200, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNull("There should not be record data returned...", jsonData.record);
        });
    });

// TODO:  Add tests for versioning (perhaps in their own module)

// The output should not include children with the "children" option set to false
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to false...", function() {
        // TODO:  This test depends on the existence of a single record.  We should adjust to use test data instead.
        request.get("http://localhost:" + read.config.port + "/record/xMPPChatID?children=false", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertUndefined("Record '" + jsonData.record.uniqueId + "' should not have contained any children", jsonData.record.aliases);
            }
        });
    });

// The output from "terms" and "records" should include children when the "children" option is set to true
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to true...", function() {
        request.get("http://localhost:" + read.config.port + "/record/xMPPChatID?children=true", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertNotUndefined("Record '" + jsonData.record.uniqueId + "' should have contained any children", jsonData.record.aliases);
            }
        });
    });

// The "children" parameter should not cause problems when loading something that doesn't have children (i.e. an alias)
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to true...", function() {
        request.get("http://localhost:" + read.config.port + "/record/XMPP+Chat+ID?children=true", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertUndefined("Record '" + jsonData.record.uniqueId + "' should have contained any children", jsonData.record.aliases);
            }
        });
    });

    jqUnit.onAllTestsDone.addListener(function() {
        // Shut down express (seems to happen implicitly, so commented out)
//    http.server.close();
    });
};

read.loadPouch();<commit_msg>Decreased timeout to at least ensure that tests run more quickly.<commit_after>// tests for all read methods
"use strict";
var fluid = require("infusion");
var namespace = "gpii.ctr.record.tests.read";
var read = fluid.registerNamespace(namespace);

var loader = require("../../../configs/lib/config-loader");
read.config = loader.loadConfig(require("../../../configs/express/test-pouch.json"));

var testUtils = require("../../tests/lib/testUtils")(read.config);

read.loadPouch = function() {
    read.pouch = require('../../tests/lib/pouch')(read.config);

    read.pouch.start(function() {
        read.startExpress();
    });
};

// Spin up an express instance
read.startExpress = function() {
    read.express = require('../../tests/lib/express')(read.config);

    read.express.start(function() {

        // Mount all variations on the module
        var record = require('../../record')(read.config);
        read.express.app.use('/record', record);

        // Add PouchDB with simulated CouchDb REST endpoints
        read.express.app.use('/pouch', require('express-pouchdb')(read.pouch.MemPouchDB));

        // Give express-pouch a few seconds to start up
        setTimeout(read.loadData, 500);
    });
};

read.loadData = function() {
    read.pouch.loadData(read.runTests);
};

read.runTests = function() {
    var jqUnit = fluid.require("jqUnit");
    var request = require('request');
    jqUnit.module("Record API (read)");

    jqUnit.asyncTest("Test retrieving record by its uniqueID", function() {
        request.get("http://localhost:" + read.config.port + "/record/org.gnome.settings-daemon.peripherals.wacom.stylus.pressurecurve", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertEquals("The request should have been successful...", 200, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNotNull("There should be record data returned...", jsonData.record);

            if (jsonData.record) {
                testUtils.isSaneRecord(jqUnit, jsonData.record);
            }
        });
    });

    jqUnit.asyncTest("Test retrieving a record that does not exist", function() {
        request.get("http://localhost:" + read.config.port + "/record/totallyBogusFlibbertyGibbit", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertEquals("The request should returned a 404 (not found)...", 404, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNull("There should not be record data returned...", jsonData.record);
        });
    });

    jqUnit.asyncTest("Test retrieving a record that does not exist", function() {
        request.get("http://localhost:" + read.config.port + "/record/", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);

            jqUnit.assertNotEquals("The request should not be successful...", 200, response.statusCode);

            var jsonData = JSON.parse(body);

            jqUnit.assertNull("There should not be record data returned...", jsonData.record);
        });
    });

// TODO:  Add tests for versioning (perhaps in their own module)

// The output should not include children with the "children" option set to false
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to false...", function() {
        // TODO:  This test depends on the existence of a single record.  We should adjust to use test data instead.
        request.get("http://localhost:" + read.config.port + "/record/xMPPChatID?children=false", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertUndefined("Record '" + jsonData.record.uniqueId + "' should not have contained any children", jsonData.record.aliases);
            }
        });
    });

// The output from "terms" and "records" should include children when the "children" option is set to true
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to true...", function() {
        request.get("http://localhost:" + read.config.port + "/record/xMPPChatID?children=true", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertNotUndefined("Record '" + jsonData.record.uniqueId + "' should have contained any children", jsonData.record.aliases);
            }
        });
    });

// The "children" parameter should not cause problems when loading something that doesn't have children (i.e. an alias)
    jqUnit.asyncTest("Retrieve record with the 'children' argument set to true...", function() {
        request.get("http://localhost:" + read.config.port + "/record/XMPP+Chat+ID?children=true", function(error, response, body) {
            jqUnit.start();

            testUtils.isSaneResponse(jqUnit, error, response, body);
            var jsonData = JSON.parse(body);

            jqUnit.assertTrue("There should have been a record returned...", jsonData.record);
            if (jsonData.record) {
                jqUnit.assertUndefined("Record '" + jsonData.record.uniqueId + "' should have contained any children", jsonData.record.aliases);
            }
        });
    });

    jqUnit.onAllTestsDone.addListener(function() {
        // Shut down express (seems to happen implicitly, so commented out)
//    http.server.close();
    });
};

read.loadPouch();<|endoftext|>


<commit_before>define(["underscore", "backbone", "moxie.conf"], function(_, Backbone, conf){
    var EVENT_POSITION_UPDATED = 'position:updated';
    function UserPosition() {
        _.extend(this, Backbone.Events);
        var supportsGeoLocation = Boolean(navigator.geolocation),
            spamReduction = false,
            missedUpdate = null,
            watchID;
        function locationSuccess(position) {
            // Trigger relevant events for any components listening to the user position
            //
            // The complexity here comes from not wanting to "spam" the geolocation API's
            // Previously we fired callbacks whenever the position updated, If the callbacks
            // were drawing the map it would severely effect performance on the device as
            // redrawing the map wouldn't finish before starting the next redraw.
            //
            // Now we have a configurable throttle to reduce this effect. No callbacks will
            // be fired within length of this throttle.
            if (spamReduction) {
                // Capture any missed updates whilst we're in "spam reduction mode"
                missedUpdate = position;
            } else {
                this.trigger(EVENT_POSITION_UPDATED, position);
                this.latest = position;
                spamReduction = true;
                setTimeout(_.bind(function() {
                    spamReduction = false;
                    if (missedUpdate) {
                        locationSuccess.apply(this, [missedUpdate]);
                        missedUpdate = null;
                    }
                }, this), conf.position.updateThrottle);
            }
        }
        function locationError() {
            if (!this.latest) {
                // We have no good position data so update to the default location
                this.latest = conf.defaultLocation;
                this.trigger(EVENT_POSITION_UPDATED, conf.defaultLocation);
            }
        }
        function startWatching() {
            if (supportsGeoLocation) {
                watchID = navigator.geolocation.watchPosition(_.bind(locationSuccess, this), _.bind(locationError, this),
                    {
                        enableHighAccuracy: true,
                        maximumAge: 120000,  // 2 minutes
                        timeout: 25000,      // 25 seconds
                    });
            } else {
                locationError.apply(this);
            }
        }
        var count = 0;
        this.follow = function(cb) {
            if (!watchID) {
                // Call the "private" function with the correct context
                startWatching.apply(this);
            }
            this.on(EVENT_POSITION_UPDATED, cb);
            if (this.latest) {
                // New subscribers should get the latest location fix
                this.trigger(EVENT_POSITION_UPDATED, this.latest);
            }
            this.count++;
        };
        this.unfollow = function(cb) {
            this.off(EVENT_POSITION_UPDATED, cb);
            this.count--;
            if (this.count === 0) {
                navigator.geolocation.clearWatch(watchID);
            }
        };
    }
    return new UserPosition();
});
<commit_msg>Added a new position API "getLocation"<commit_after>define(["underscore", "backbone", "moxie.conf"], function(_, Backbone, conf){
    var EVENT_POSITION_UPDATED = 'position:updated';
    function UserPosition() {
        _.extend(this, Backbone.Events);
        var supportsGeoLocation = Boolean(navigator.geolocation),
            spamReduction = false,
            missedUpdate = null,
            watchID;
        this.getLocation = function(cb, options) {
            options = options || {};
            // Default options:
            // errorMargin = 50 meters
            // timeout     = 30 seconds
            //
            // If we don't get a location within the errorMargin after before the Timeout
            // we return the most recent position reported by watchPosition
            options.errorMargin = options.errorMargin || 50;
            options.timeout = options.timeout || 30000;
            var watchID;
            var latestPosition;
            var accuracyTimeout = setTimeout(function() {
                navigator.geolocation.clearWatch(watchID);
            }, options.timeout);
            watchID = navigator.geolocation.watchPosition(function(position) {
                latestPosition = position;
                if (latestPosition.coords && latestPosition.coords.accuracy && latestPosition.coords.accuracy < options.errorMargin) {
                    window.clearTimeout(accuracyTimeout);
                    navigator.geolocation.clearWatch(watchID);
                    cb(latestPosition);
                }
            }, _.bind(locationError, this),
            {
                    enableHighAccuracy: true,
                    maximumAge: 120000,  // 2 minutes
            });

        };
        function locationSuccess(position) {
            // Trigger relevant events for any components listening to the user position
            //
            // The complexity here comes from not wanting to "spam" the geolocation API's
            // Previously we fired callbacks whenever the position updated, If the callbacks
            // were drawing the map it would severely effect performance on the device as
            // redrawing the map wouldn't finish before starting the next redraw.
            //
            // Now we have a configurable throttle to reduce this effect. No callbacks will
            // be fired within length of this throttle.
            if (spamReduction) {
                // Capture any missed updates whilst we're in "spam reduction mode"
                missedUpdate = position;
            } else {
                this.trigger(EVENT_POSITION_UPDATED, position);
                this.latest = position;
                spamReduction = true;
                setTimeout(_.bind(function() {
                    spamReduction = false;
                    if (missedUpdate) {
                        locationSuccess.apply(this, [missedUpdate]);
                        missedUpdate = null;
                    }
                }, this), conf.position.updateThrottle);
            }
        }
        function locationError() {
            if (!this.latest) {
                // We have no good position data so update to the default location
                this.latest = conf.defaultLocation;
                this.trigger(EVENT_POSITION_UPDATED, conf.defaultLocation);
            }
        }
        function startWatching() {
            if (supportsGeoLocation) {
                watchID = navigator.geolocation.watchPosition(_.bind(locationSuccess, this), _.bind(locationError, this),
                    {
                        enableHighAccuracy: true,
                        maximumAge: 120000,  // 2 minutes
                        timeout: 25000,      // 25 seconds
                    });
            } else {
                locationError.apply(this);
            }
        }
        var count = 0;
        this.follow = function(cb) {
            if (!watchID) {
                // Call the "private" function with the correct context
                startWatching.apply(this);
            }
            this.on(EVENT_POSITION_UPDATED, cb);
            if (this.latest) {
                // New subscribers should get the latest location fix
                this.trigger(EVENT_POSITION_UPDATED, this.latest);
            }
            this.count++;
        };
        this.unfollow = function(cb) {
            this.off(EVENT_POSITION_UPDATED, cb);
            this.count--;
            if (this.count === 0) {
                navigator.geolocation.clearWatch(watchID);
            }
        };
    }
    return new UserPosition();
});
<|endoftext|>


<commit_before>/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app');

var app = new EmberApp();

// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree();
<commit_msg>feat(Brocfile): update brocoly configuration<commit_after>/* global require, module */

var EmberApp = require('ember-cli/lib/broccoli/ember-app');

var app = new EmberApp();
//app.import('bower_components/ember/ember-template-compiler.js');

app.import('bower_components/lodash/lodash.js');

//var HtmlbarsCompiler = require('ember-cli-htmlbars');
//
//var templateTree = new HtmlbarsCompiler('app/templates', {
//  isHTMLBars: true,
//
//  // provide the templateCompiler that is paired with your Ember version
//  templateCompiler: require('./bower_components/ember/ember-template-compiler')
//});

// Use `app.import` to add additional libraries to the generated
// output files.
//
// If you need to use different assets in different
// environments, specify an object as the first parameter. That
// object's keys should be the environment name and the values
// should be the asset to use in that environment.
//
// If the library that you are including contains AMD or ES6
// modules that you would like to import into your application
// please specify an object with the list of modules as keys
// along with the exports of each module as its value.

module.exports = app.toTree();
<|endoftext|>


<commit_before>import {
	call,
	put,
	takeLatest,
	race,
	select
} from 'redux-saga/effects'
import { delay } from 'redux-saga'
import { Alert } from 'react-native'
import firebase from 'react-native-firebase'

import ssoService from '../services/ssoService'
import userService from '../services/userService'
import {
	SSO_TTL,
	SSO_IDP_ERROR_RETRY_INCREMENT,
	USER_PROFILE_SYNC_TTL,
	UCSD_STUDENT
} from '../AppSettings'
import logger from '../util/logger'

const auth = require('../util/auth')

const userState = state => (state.user)

// This function is used when a user manually submits
// credentials to sign in with.
function* doLogin(action) {
	const { username, password } = action

	yield put({ type: 'LOG_IN_REQUEST' })
	try {
		if (!password || password.length === 0) {
			const e = new Error('Please type in your password.')
			e.name = 'emptyPasswordError'
			yield call(delay, 0)
			throw e
		}
		const passwordEncrypted = yield auth.encryptStringWithKey(password)
		const loginInfo = auth.encryptStringWithBase64(`${username}:${passwordEncrypted}`)

		const { response, timeout } = yield race({
			response: call(ssoService.retrieveAccessToken, loginInfo),
			timeout: call(delay, SSO_TTL)
		})

		if (timeout) {
			const e = new Error('Logging in timed out.')
			e.name = 'ssoTimeout'
			throw e
		} else if (response.error) {
			if (response.error.appUpdateRequired) {
				yield outOfDateAlert()
				const appUpdateError = new Error('App update required.')
				throw appUpdateError
			} else {
				logger.log(response)
				throw response.error
			}
		} else {
			// Successfully logged in
			yield auth.storeUserCreds(username, passwordEncrypted)
			yield auth.storeAccessToken(response.access_token)

			// Set up user profile
			const isStudent = Boolean((response.pid) && (response.ucsdaffiliation.match(UCSD_STUDENT)))

			const newProfile = {
				username,
				pid: response.pid,
				ucsdaffiliation: response.ucsdaffiliation,
				classifications: {
					student: isStudent
				}
			}

			// Post sign-in flow
			// Toggles any cards that should show up for the signed in user
			// Registers firebase push token
			// Queries any user data with newly obtained access token
			yield put({ type: 'LOGGED_IN', profile: newProfile })
			yield put({ type: 'LOG_IN_SUCCESS' })
			yield put({ type: 'TOGGLE_AUTHENTICATED_CARDS' })

			const fcmToken = yield firebase.messaging().getToken()
			if (fcmToken) yield put({ type: 'REGISTER_TOKEN', token: fcmToken })

			// Clears any potential errors from being
			// unable to automatically reauthorize a user
			yield put({ type: 'AUTH_HTTP_SUCCESS' })

			yield call(queryUserData)
		}
	} catch (error) {
		logger.trackException(error)
		yield put({ type: 'LOG_IN_FAILURE', error })
	}
}

function* queryUserData() {
	// USER PROFILE SYNC
	// Sync user profile from cloud when first logging in
	yield call(getUserProfile)
	const { profile, syncedProfile } = yield select(userState)

	// If newly signed in user fits into certain categories,
	// subscribe them to their topics.
	if (profile.classifications) {
		if (profile.classifications.student) {
			// subscribe to default student topics
			yield put({ type: 'SUBSCRIBE_TO_TOPIC', topicId: 'students' })
		}
	}

	// If their synced profile has unsubscribed from these topics,
	// that is synced in the next few steps and handled accordingly

	// populate newProfile with potentially stale remote data first
	let profileItems = { ...syncedProfile }

	// add newly initialized profile object
	profileItems = { ...profileItems }

	// only sync data that is dependent on the user signing in
	if (profile.username) profileItems.username = profile.username
	if (profile.classifications) profileItems.classifications = { ...profile.classifications }
	if (profile.pid) profileItems.pid = profile.pid
	if (profile.ucsdaffiliation) profileItems.ucsdaffiliation = profile.ucsdaffiliation

	const modifyProfileAction = { profileItems }

	yield call(modifyLocalProfile, modifyProfileAction)

	// subscribes to firebase topics that have been synced from the server
	yield put({ type: 'REFRESH_TOPIC_SUBSCRIPTIONS' })

	// INITIAL USER DATA CALLS
	// perform first data calls when user is logged in
	yield put({ type: 'UPDATE_SCHEDULE' })
	yield put({ type: 'UPDATE_MESSAGES' })
}
// Used when an API call requires an access token and the current
// one is stale.
function* doTokenRefresh() {
	try {
		yield refreshTokenRequest()
	} catch (error) {
		const invalidCredsMessage = 'Be sure you are using the correct credentials; TritonLink login if you are a student, SSO if you are Faculty/Staff.'
		if (error.message === invalidCredsMessage) {
			// This means that the authentication server rejected our
			// saved credentials. Did the user's password change? Only retry
			// once, and if it fails again, force a sign-out.
			try {
				// Try once more with a delay just to be sure
				yield delay(SSO_IDP_ERROR_RETRY_INCREMENT)
				yield refreshTokenRequest()
			} catch (secondError) {
				if (secondError.message === invalidCredsMessage) {
					// We tried again and got the same error
					yield put({ type: 'PANIC_LOG_OUT' })
					const invalidCredsError = new Error('InvalidCreds Error')
					logger.trackException(invalidCredsError)
					yield call(clearUserData)
				}
			}
		}
	}
}

// Utility method that actually makes the request for the new
// access token using encrypted stored credentials
function* refreshTokenRequest() {
	const { isLoggedIn } = yield select(userState)
	if (!isLoggedIn) {
		const e = new Error('Not signed in.')
		throw e
	}

	// Get username and password from keystore
	const {
		username,
		password
	} = yield auth.retrieveUserCreds()
	const loginInfo = auth.encryptStringWithBase64(`${username}:${password}`)
	const response = yield call(ssoService.retrieveAccessToken, loginInfo)

	if (response.error && response.error.appUpdateRequired) {
		yield outOfDateAlert()
	} else if (response.access_token) {
		yield auth.storeAccessToken(response.access_token)
		// Clears any potential errors from being
		// unable to automatically reauthorize a user

		// Set up user profile
		const isStudent = Boolean((response.pid) && (response.ucsdaffiliation.match(UCSD_STUDENT)))
		const newProfile = {
			username,
			pid: response.pid,
			ucsdaffiliation: response.ucsdaffiliation,
			classifications: {
				student: isStudent
			}
		}

		// Post sign-in flow
		// Toggles any cards that should show up for the signed in user
		// Registers firebase push token
		// Queries any user data with newly obtained access token
		yield put({ type: 'LOGGED_IN', profile: newProfile })
		yield put({ type: 'AUTH_HTTP_SUCCESS' })
	} else {
		const e = new Error('No access token returned.')
		throw e
	}
}

// Obtains the user profile stored in the cloud
function* getUserProfile() {
	// Request user profile from API
	yield put({ type: 'GET_PROFILE_REQUEST' })

	try {
		const profile = yield call(userService.FetchUserProfile)
		yield put({ type: 'GET_PROFILE_SUCCESS' })

		if (profile) {
			yield put({ type: 'SET_USER_PROFILE', profileItems: profile })
		}
	} catch (error) {
		yield put({ type: 'GET_PROFILE_FAILURE' })
		logger.trackException(error)
	}
}

// Times out any current logging-in process
function* doTimeOut() {
	const error = new Error('Logging in timed out.')
	yield put({ type: 'LOG_IN_FAILURE', error })
}

// Logs out the user
function* doLogout(action) {
	const { profile } = yield select(userState)
	const { subscribedTopics: currentSubscriptions } = profile

	// We need to pass in the accessToken before we lose it
	// This isn't guaranteed to work but we should try anyways
	const accessToken = yield auth.retrieveAccessToken()
	yield put({ type: 'UNREGISTER_TOKEN', accessToken })

	yield put({ type: 'LOGGED_OUT' })
	yield call(clearUserData, currentSubscriptions)
}

function* outOfDateAlert() {
	yield put({ type: 'APP_UPDATE_REQUIRED' })

	Alert.alert(
		'App Update Required',
		'If you would like to log in, please update the app.',
		[
			{
				text: 'OK',
				style: 'cancel'
			}
		],
		{ cancelable: false }
	)
}

// Syncs local profile with remote user profile stored in the cloud
function* syncUserProfile() {
	const { isLoggedIn, profile, lastSynced } = yield select(userState)

	if (!isLoggedIn) return

	const nowTime = new Date().getTime()
	const timeDiff = nowTime - lastSynced
	const syncTTL = USER_PROFILE_SYNC_TTL

	if (timeDiff < syncTTL) return

	// Update remote profile with local one
	const newAttributes = []

	Object.keys(profile).forEach((key) => {
		newAttributes.push({
			attribute: key,
			value: profile[key],
		})
	})

	yield put({ type: 'POST_PROFILE_REQUEST' })
	try {
		yield call(userService.PostUserProfile, newAttributes)
		// Get latest profile from server
		yield call(getUserProfile)
		yield put({ type: 'POST_PROFILE_SUCCESS' })
		yield put({ type: 'PROFILE_SYNCED' })

		// subscribes to firebase topics that have been synced from the server
		yield put({ type: 'REFRESH_TOPIC_SUBSCRIPTIONS' })
	} catch (error) {
		yield put({ type: 'POST_PROFILE_FAILURE' })
		logger.trackException(error)
	}
}

// Handles modifying the local user profile object.
// If the user is signed in, initiates a sync attempt
// with the remote server
function* modifyLocalProfile(action) {
	const { profileItems } = action

	yield put({ type: 'SET_LOCAL_PROFILE', profileItems })
	yield put({ type: 'RESET_SYNCED_DATE' })
	yield call(syncUserProfile)

	// if profile change includes changes to subscriptions, reset messages
	if (profileItems.subscribedTopics) yield put({ type: 'RESET_MESSAGES' })
}

// Performs various cleanup actions. These include:
// Unregistering / unassociating the firebase push token
// Clearing any user specific data (but not any default preferences
// such as card order or subscriptions to default notification categories)
function* clearUserData(currentSubscriptions) {
	yield put({ type: 'TOGGLE_AUTHENTICATED_CARDS' })
	yield auth.destroyUserCreds()
	yield auth.destroyAccessToken()
	yield put({ type: 'CLEAR_SCHEDULE_DATA' })
	yield put({ type: 'CLEAR_USER_SUBSCRIPTIONS', subscribedTopics: currentSubscriptions })
	yield put({ type: 'RESET_MESSAGES' })
}

function* userSaga() {
	yield takeLatest('USER_LOGIN', doLogin)
	yield takeLatest('USER_LOGOUT', doLogout)
	yield takeLatest('USER_LOGIN_TIMEOUT', doTimeOut)
	yield takeLatest('USER_TOKEN_REFRESH', doTokenRefresh)
	yield takeLatest('GET_USER_PROFILE', getUserProfile)
	yield takeLatest('MODIFY_LOCAL_PROFILE', modifyLocalProfile)
	yield takeLatest('SYNC_USER_PROFILE', syncUserProfile)
}

export default userSaga
<commit_msg>Remove one hour sync constraint from userSaga<commit_after>import {
	call,
	put,
	takeLatest,
	race,
	select
} from 'redux-saga/effects'
import { delay } from 'redux-saga'
import { Alert } from 'react-native'
import firebase from 'react-native-firebase'

import ssoService from '../services/ssoService'
import userService from '../services/userService'
import {
	SSO_TTL,
	SSO_IDP_ERROR_RETRY_INCREMENT,
	USER_PROFILE_SYNC_TTL,
	UCSD_STUDENT
} from '../AppSettings'
import logger from '../util/logger'

const auth = require('../util/auth')

const userState = state => (state.user)

// This function is used when a user manually submits
// credentials to sign in with.
function* doLogin(action) {
	const { username, password } = action

	yield put({ type: 'LOG_IN_REQUEST' })
	try {
		if (!password || password.length === 0) {
			const e = new Error('Please type in your password.')
			e.name = 'emptyPasswordError'
			yield call(delay, 0)
			throw e
		}
		const passwordEncrypted = yield auth.encryptStringWithKey(password)
		const loginInfo = auth.encryptStringWithBase64(`${username}:${passwordEncrypted}`)

		const { response, timeout } = yield race({
			response: call(ssoService.retrieveAccessToken, loginInfo),
			timeout: call(delay, SSO_TTL)
		})

		if (timeout) {
			const e = new Error('Logging in timed out.')
			e.name = 'ssoTimeout'
			throw e
		} else if (response.error) {
			if (response.error.appUpdateRequired) {
				yield outOfDateAlert()
				const appUpdateError = new Error('App update required.')
				throw appUpdateError
			} else {
				logger.log(response)
				throw response.error
			}
		} else {
			// Successfully logged in
			yield auth.storeUserCreds(username, passwordEncrypted)
			yield auth.storeAccessToken(response.access_token)

			// Set up user profile
			const isStudent = Boolean((response.pid) && (response.ucsdaffiliation.match(UCSD_STUDENT)))

			const newProfile = {
				username,
				pid: response.pid,
				ucsdaffiliation: response.ucsdaffiliation,
				classifications: {
					student: isStudent
				}
			}

			// Post sign-in flow
			// Toggles any cards that should show up for the signed in user
			// Registers firebase push token
			// Queries any user data with newly obtained access token
			yield put({ type: 'LOGGED_IN', profile: newProfile })
			yield put({ type: 'LOG_IN_SUCCESS' })
			yield put({ type: 'TOGGLE_AUTHENTICATED_CARDS' })

			const fcmToken = yield firebase.messaging().getToken()
			if (fcmToken) yield put({ type: 'REGISTER_TOKEN', token: fcmToken })

			// Clears any potential errors from being
			// unable to automatically reauthorize a user
			yield put({ type: 'AUTH_HTTP_SUCCESS' })

			yield call(queryUserData)
		}
	} catch (error) {
		logger.trackException(error)
		yield put({ type: 'LOG_IN_FAILURE', error })
	}
}

function* queryUserData() {
	// USER PROFILE SYNC
	// Sync user profile from cloud when first logging in
	yield call(getUserProfile)
	const { profile, syncedProfile } = yield select(userState)

	// If newly signed in user fits into certain categories,
	// subscribe them to their topics.
	if (profile.classifications) {
		if (profile.classifications.student) {
			// subscribe to default student topics
			yield put({ type: 'SUBSCRIBE_TO_TOPIC', topicId: 'students' })
		}
	}

	// If their synced profile has unsubscribed from these topics,
	// that is synced in the next few steps and handled accordingly

	// populate newProfile with potentially stale remote data first
	let profileItems = { ...syncedProfile }

	// add newly initialized profile object
	profileItems = { ...profileItems }

	// only sync data that is dependent on the user signing in
	if (profile.username) profileItems.username = profile.username
	if (profile.classifications) profileItems.classifications = { ...profile.classifications }
	if (profile.pid) profileItems.pid = profile.pid
	if (profile.ucsdaffiliation) profileItems.ucsdaffiliation = profile.ucsdaffiliation

	const modifyProfileAction = { profileItems }

	yield call(modifyLocalProfile, modifyProfileAction)

	// subscribes to firebase topics that have been synced from the server
	yield put({ type: 'REFRESH_TOPIC_SUBSCRIPTIONS' })

	// INITIAL USER DATA CALLS
	// perform first data calls when user is logged in
	yield put({ type: 'UPDATE_SCHEDULE' })
	yield put({ type: 'UPDATE_MESSAGES' })
}
// Used when an API call requires an access token and the current
// one is stale.
function* doTokenRefresh() {
	try {
		yield refreshTokenRequest()
	} catch (error) {
		const invalidCredsMessage = 'Be sure you are using the correct credentials; TritonLink login if you are a student, SSO if you are Faculty/Staff.'
		if (error.message === invalidCredsMessage) {
			// This means that the authentication server rejected our
			// saved credentials. Did the user's password change? Only retry
			// once, and if it fails again, force a sign-out.
			try {
				// Try once more with a delay just to be sure
				yield delay(SSO_IDP_ERROR_RETRY_INCREMENT)
				yield refreshTokenRequest()
			} catch (secondError) {
				if (secondError.message === invalidCredsMessage) {
					// We tried again and got the same error
					yield put({ type: 'PANIC_LOG_OUT' })
					const invalidCredsError = new Error('InvalidCreds Error')
					logger.trackException(invalidCredsError)
					yield call(clearUserData)
				}
			}
		}
	}
}

// Utility method that actually makes the request for the new
// access token using encrypted stored credentials
function* refreshTokenRequest() {
	const { isLoggedIn } = yield select(userState)
	if (!isLoggedIn) {
		const e = new Error('Not signed in.')
		throw e
	}

	// Get username and password from keystore
	const {
		username,
		password
	} = yield auth.retrieveUserCreds()
	const loginInfo = auth.encryptStringWithBase64(`${username}:${password}`)
	const response = yield call(ssoService.retrieveAccessToken, loginInfo)

	if (response.error && response.error.appUpdateRequired) {
		yield outOfDateAlert()
	} else if (response.access_token) {
		yield auth.storeAccessToken(response.access_token)
		// Clears any potential errors from being
		// unable to automatically reauthorize a user

		// Set up user profile
		const isStudent = Boolean((response.pid) && (response.ucsdaffiliation.match(UCSD_STUDENT)))
		const newProfile = {
			username,
			pid: response.pid,
			ucsdaffiliation: response.ucsdaffiliation,
			classifications: {
				student: isStudent
			}
		}

		// Post sign-in flow
		// Toggles any cards that should show up for the signed in user
		// Registers firebase push token
		// Queries any user data with newly obtained access token
		yield put({ type: 'LOGGED_IN', profile: newProfile })
		yield put({ type: 'AUTH_HTTP_SUCCESS' })
	} else {
		const e = new Error('No access token returned.')
		throw e
	}
}

// Obtains the user profile stored in the cloud
function* getUserProfile() {
	// Request user profile from API
	yield put({ type: 'GET_PROFILE_REQUEST' })

	try {
		const profile = yield call(userService.FetchUserProfile)
		yield put({ type: 'GET_PROFILE_SUCCESS' })

		if (profile) {
			yield put({ type: 'SET_USER_PROFILE', profileItems: profile })
		}
	} catch (error) {
		yield put({ type: 'GET_PROFILE_FAILURE' })
		logger.trackException(error)
	}
}

// Times out any current logging-in process
function* doTimeOut() {
	const error = new Error('Logging in timed out.')
	yield put({ type: 'LOG_IN_FAILURE', error })
}

// Logs out the user
function* doLogout(action) {
	const { profile } = yield select(userState)
	const { subscribedTopics: currentSubscriptions } = profile

	// We need to pass in the accessToken before we lose it
	// This isn't guaranteed to work but we should try anyways
	const accessToken = yield auth.retrieveAccessToken()
	yield put({ type: 'UNREGISTER_TOKEN', accessToken })

	yield put({ type: 'LOGGED_OUT' })
	yield call(clearUserData, currentSubscriptions)
}

function* outOfDateAlert() {
	yield put({ type: 'APP_UPDATE_REQUIRED' })

	Alert.alert(
		'App Update Required',
		'If you would like to log in, please update the app.',
		[
			{
				text: 'OK',
				style: 'cancel'
			}
		],
		{ cancelable: false }
	)
}

// Syncs local profile with remote user profile stored in the cloud
function* syncUserProfile() {
	const { isLoggedIn, profile } = yield select(userState)

	if (!isLoggedIn) return

	// Update remote profile with local one
	const newAttributes = []

	Object.keys(profile).forEach((key) => {
		newAttributes.push({
			attribute: key,
			value: profile[key],
		})
	})

	yield put({ type: 'POST_PROFILE_REQUEST' })
	try {
		yield call(userService.PostUserProfile, newAttributes)
		// Get latest profile from server
		yield call(getUserProfile)
		yield put({ type: 'POST_PROFILE_SUCCESS' })
		yield put({ type: 'PROFILE_SYNCED' })

		// subscribes to firebase topics that have been synced from the server
		yield put({ type: 'REFRESH_TOPIC_SUBSCRIPTIONS' })
	} catch (error) {
		yield put({ type: 'POST_PROFILE_FAILURE' })
		logger.trackException(error)
	}
}

// Handles modifying the local user profile object.
// If the user is signed in, initiates a sync attempt
// with the remote server
function* modifyLocalProfile(action) {
	const { profileItems } = action

	yield put({ type: 'SET_LOCAL_PROFILE', profileItems })
	yield put({ type: 'RESET_SYNCED_DATE' })
	yield call(syncUserProfile)

	// if profile change includes changes to subscriptions, reset messages
	if (profileItems.subscribedTopics) yield put({ type: 'RESET_MESSAGES' })
}

// Performs various cleanup actions. These include:
// Unregistering / unassociating the firebase push token
// Clearing any user specific data (but not any default preferences
// such as card order or subscriptions to default notification categories)
function* clearUserData(currentSubscriptions) {
	yield put({ type: 'TOGGLE_AUTHENTICATED_CARDS' })
	yield auth.destroyUserCreds()
	yield auth.destroyAccessToken()
	yield put({ type: 'CLEAR_SCHEDULE_DATA' })
	yield put({ type: 'CLEAR_USER_SUBSCRIPTIONS', subscribedTopics: currentSubscriptions })
	yield put({ type: 'RESET_MESSAGES' })
}

function* userSaga() {
	yield takeLatest('USER_LOGIN', doLogin)
	yield takeLatest('USER_LOGOUT', doLogout)
	yield takeLatest('USER_LOGIN_TIMEOUT', doTimeOut)
	yield takeLatest('USER_TOKEN_REFRESH', doTokenRefresh)
	yield takeLatest('GET_USER_PROFILE', getUserProfile)
	yield takeLatest('MODIFY_LOCAL_PROFILE', modifyLocalProfile)
	yield takeLatest('SYNC_USER_PROFILE', syncUserProfile)
}

export default userSaga
<|endoftext|>


<commit_before>/**
 *
 * htmlQM Module
 *
 */
define([
    'jquery',
    'underscore',
    'Helpers'
], function(
    $,
    _,
    Helpers
) {
    var QMHtml = {};

    QMHtml.VideoChat = {

        onCallTpl: function(params) {
            var htmlTemplate = _.template('
' +
                '
' +
                '<div class="message-avatar avatar info-avatar" style="background-image:url(<%= userAvatar %>)">
' +
                '<%= callTypeUС %> Call from <%= userName %>
' +
                '
' +
                '<button class="btn_decline" data-callType="<%= callType %>" data-dialog="<%= dialogId %>"' +
                ' data-id="<%= userId %>">Decline</button>' +
                '<button class="btn_accept" data-callType="<%= callType %>" data-session="<%= sessionId %>"' +
                ' data-dialog="<%= dialogId %>" data-id="<%= userId %>">Accept</button>' +
                '

')(params);

            return htmlTemplate;
        },

        buildTpl: function(params) {
            var htmlTemplate = _.template('
' +
                '<video id="remoteStream" class="mediacall-remote-stream is-hidden"></video>' +
                '<video id="localStream" class="mediacall-local mediacall-local-stream is-hidden"></video>' +
                '<img id="localUser" class="mediacall-local mediacall-local-avatar" src="<%=userAvatar%>" alt="avatar">' +
                '
' +
                '<img class="mediacall-remote-avatar" src="<%=contactAvatar%>" alt="avatar">' +
                '<%=contactName%>
' +
                '
' +
                '' +
                'connect...
' +
                '
' +
                '<button class="btn_mediacall btn_full-mode" data-id="<%=userId%>" data-dialog="<%=dialogId%>" disabled>' +
                '

' +
                '

</button>' +
                '<button class="btn_mediacall btn_camera_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '<button class="btn_mediacall btn_mic_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '<button class="btn_mediacall btn_hangup" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '

')(params);

            return htmlTemplate;
        },

        showError: function() {
            var isBottom = Helpers.isBeginOfChat(),
                $chat = $('.l-chat:visible'),
                $html = $('
' +
                    '' +
                    '
' +
                    '
' +
                    '

Camera and/or microphone wasn\'t found.' +
                    '

');

            $chat.find('.mCSB_container').append($html);

            if (isBottom) {
                $chat.find('.j-scrollbar_message').mCustomScrollbar('scrollTo', 'bottom');
            }
        },

        noWebRTC: function() {
            var isBottom = Helpers.isBeginOfChat(),
                $chat = $('.l-chat:visible'),
                $html = $('
' +
                    '' +
                    '
' +
                    '
' +
                    '

' +
                    'Audio and Video calls aren\'t supported by your browser. Please use Google Chrome, Opera or Firefox.' +
                    '

');

            $chat.find('.mCSB_container').append($html);

            if (isBottom) {
                $chat.find('.j-scrollbar_message').mCustomScrollbar('scrollTo', 'bottom');
            }
        }

    };

    QMHtml.User = {

        contactPopover: function(params, roster) {
            var $html = $('

'),
                htmlStr = '';

            if (params.dialogType === 3 && roster && roster.subscription !== 'none') {
                htmlStr = '
<a class="videoCall list-actions-action writeMessage" data-id="<%=ids%>" href="#">Video call
' +
                    '
<a class="audioCall list-actions-action writeMessage" data-id="<%=ids%>" href="#">Audio call
' +
                    '
<a class="list-actions-action createGroupChat" data-ids="<%=ids%>" data-private="1" href="#">Add people
';
            } else if (params.dialogType !== 3) {
                htmlStr = '
<a class="list-actions-action addToGroupChat" data-group="true" data-ids="<%=occupantsIds%>" ' +
                    'data-dialog="<%=dialogId%>" href="#">Add people
';
            }

            if (params.dialogType === 3) {
                htmlStr += '
Delete contact
' +
                    '
<a class="list-actions-action userDetails" data-id="<%=ids%>" href="#">Profile
';
            }
                htmlStr += '
Remove chat
';

            return $html.append(_.template(htmlStr)(params));
        },

        occupantPopover: function(params, roster) {
            var $html = $('

'),
                htmlStr = '';

            if (!roster || (roster.subscription === 'none' && !roster.ask)) {
                htmlStr = '<li class="list-item j-listItem" data-jid="<%=jid%>">' +
                    '<a class="list-actions-action requestAction j-requestAction" data-id="<%=id%>" href="#">Send request
';
            } else if (roster.ask === 'subscribe' && !roster.status) {
                htmlStr = '
<a class="list-actions-action userDetails" data-id="<%=id%>" href="#">Profile
' +
                    '
<a class="deleteContact list-actions-action" data-id="<%=id%>" href="#">Delete contact
';
            } else {
                htmlStr = '
<a class="videoCall list-actions-action writeMessage" data-id="<%=id%>" href="#">Video call
' +
                    '
<a class="audioCall list-actions-action writeMessage" data-id="<%=id%>" href="#">Audio call
' +
                    '
<a class="list-actions-action writeMessage" data-id="<%=id%>" href="#">Write message
' +
                    '
<a class="list-actions-action userDetails" data-id="<%=id%>" href="#">Profile
';
            }

            return $html.append(_.template(htmlStr)(params));
        },

        getControlButtonsForPopupDetails: function(roster) {
            var $html = $('#popupDetails').find('.userDetails-controls'),
                htmlStr = '',
                params = {
                    roster: 'ask_subscription'
                };

            if (roster.subscription !== 'none' && roster.ask === null) {
                params.roster = '';
                htmlStr =
                    '
' +
                    '
' +
                    '
Make video call
' +
                    '
' +
                    '
' +
                    '
Make audio call
';
            }

            htmlStr += '<div class="btn_userDetails <%=roster%> writeMessage">' +
                '
' +
                '
Send message
' +
                '<div class="btn_userDetails <%=roster%> deleteContact">' +
                '
' +
                '
Remove contact and chat
';

            $html.empty();
            $html.append(_.template(htmlStr)(params));
        },

        profilePopover: function() {
            var html = $('
' +
                '
Profile
' +
                '
Settings
' +
                '
Log Out

');

            return html;
        }

    };

    QMHtml.Messages = {

        setMap: function(params) {
            var htmlTemplate = _.template(
                '<a class="open_map" href="<%=mapLink%>" target="_blank">' +
                '')(params);

            $('article#' + params.id).find('.message-geo')
                .addClass('with-geo')
                .append(htmlTemplate);
        },

        urlPreview: function(params) {
            var htmlTemplate = _.template(
                    '
<%=title%>
'+
                    '<%=description%>'+
                    '<% if (picture) { %>'+
                        '
'+
                            '<img src="<%=picture%>" alt="og_pic">'+
                        '
'+
                    '<% } %>'
                )(params);

            return htmlTemplate;
        }

    };

    QMHtml.Attach = {

        error: function(params) {
            var htmlTemplate = _.template('
'+
                ''+
                '
'+
                '
'+
                '
'+
                '
<%= errMsg %>
'+
                '

')(params);

            return htmlTemplate;
        },

        attach: function(params) {
            var htmlTemplate = _.template(
                '
' +
                '' +
                '' +
                '
' +
                '
' +
                '
' +
                '
<%= fileName %>
' +
                '<div id="progress_<%= id %>">
' +
                '<span class="attach-part attach-part_<%= id %>">' +
                ' of <%= fileSizeCrop %> <%= fileSizeUnit %>' +
                '

' +
                '<time class="message-time">Cancel</time>' +
                '

')(params);

            return htmlTemplate;
        }

    };

    QMHtml.qmplayer

    return QMHtml;
});
<commit_msg>QMPlayer added<commit_after>/**
 *
 * htmlQM Module
 *
 */
define([
    'jquery',
    'underscore',
    'Helpers'
], function(
    $,
    _,
    Helpers
) {
    var QMHtml = {};

    QMHtml.VideoChat = {

        onCallTpl: function(params) {
            var htmlTemplate = _.template('
' +
                '
' +
                '<div class="message-avatar avatar info-avatar" style="background-image:url(<%= userAvatar %>)">
' +
                '<%= callTypeUС %> Call from <%= userName %>
' +
                '
' +
                '<button class="btn_decline" data-callType="<%= callType %>" data-dialog="<%= dialogId %>"' +
                ' data-id="<%= userId %>">Decline</button>' +
                '<button class="btn_accept" data-callType="<%= callType %>" data-session="<%= sessionId %>"' +
                ' data-dialog="<%= dialogId %>" data-id="<%= userId %>">Accept</button>' +
                '

')(params);

            return htmlTemplate;
        },

        buildTpl: function(params) {
            var htmlTemplate = _.template('
' +
                '<video id="remoteStream" class="mediacall-remote-stream is-hidden"></video>' +
                '<video id="localStream" class="mediacall-local mediacall-local-stream is-hidden"></video>' +
                '<img id="localUser" class="mediacall-local mediacall-local-avatar" src="<%=userAvatar%>" alt="avatar">' +
                '
' +
                '<img class="mediacall-remote-avatar" src="<%=contactAvatar%>" alt="avatar">' +
                '<%=contactName%>
' +
                '
' +
                '' +
                'connect...
' +
                '
' +
                '<button class="btn_mediacall btn_full-mode" data-id="<%=userId%>" data-dialog="<%=dialogId%>" disabled>' +
                '

' +
                '

</button>' +
                '<button class="btn_mediacall btn_camera_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '<button class="btn_mediacall btn_mic_off" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '<button class="btn_mediacall btn_hangup" data-id="<%=userId%>" data-dialog="<%=dialogId%>">' +
                '</button>' +
                '

')(params);

            return htmlTemplate;
        },

        showError: function() {
            var isBottom = Helpers.isBeginOfChat(),
                $chat = $('.l-chat:visible'),
                $html = $('
' +
                    '' +
                    '
' +
                    '
' +
                    '

Camera and/or microphone wasn\'t found.' +
                    '

');

            $chat.find('.mCSB_container').append($html);

            if (isBottom) {
                $chat.find('.j-scrollbar_message').mCustomScrollbar('scrollTo', 'bottom');
            }
        },

        noWebRTC: function() {
            var isBottom = Helpers.isBeginOfChat(),
                $chat = $('.l-chat:visible'),
                $html = $('
' +
                    '' +
                    '
' +
                    '
' +
                    '

' +
                    'Audio and Video calls aren\'t supported by your browser. Please use Google Chrome, Opera or Firefox.' +
                    '

');

            $chat.find('.mCSB_container').append($html);

            if (isBottom) {
                $chat.find('.j-scrollbar_message').mCustomScrollbar('scrollTo', 'bottom');
            }
        }

    };

    QMHtml.User = {

        contactPopover: function(params, roster) {
            var $html = $('

'),
                htmlStr = '';

            if (params.dialogType === 3 && roster && roster.subscription !== 'none') {
                htmlStr = '
<a class="videoCall list-actions-action writeMessage" data-id="<%=ids%>" href="#">Video call
' +
                    '
<a class="audioCall list-actions-action writeMessage" data-id="<%=ids%>" href="#">Audio call
' +
                    '
<a class="list-actions-action createGroupChat" data-ids="<%=ids%>" data-private="1" href="#">Add people
';
            } else if (params.dialogType !== 3) {
                htmlStr = '
<a class="list-actions-action addToGroupChat" data-group="true" data-ids="<%=occupantsIds%>" ' +
                    'data-dialog="<%=dialogId%>" href="#">Add people
';
            }

            if (params.dialogType === 3) {
                htmlStr += '
Delete contact
' +
                    '
<a class="list-actions-action userDetails" data-id="<%=ids%>" href="#">Profile
';
            }
                htmlStr += '
Remove chat
';

            return $html.append(_.template(htmlStr)(params));
        },

        occupantPopover: function(params, roster) {
            var $html = $('

'),
                htmlStr = '';

            if (!roster || (roster.subscription === 'none' && !roster.ask)) {
                htmlStr = '<li class="list-item j-listItem" data-jid="<%=jid%>">' +
                    '<a class="list-actions-action requestAction j-requestAction" data-id="<%=id%>" href="#">Send request
';
            } else if (roster.ask === 'subscribe' && !roster.status) {
                htmlStr = '
<a class="list-actions-action userDetails" data-id="<%=id%>" href="#">Profile
' +
                    '
<a class="deleteContact list-actions-action" data-id="<%=id%>" href="#">Delete contact
';
            } else {
                htmlStr = '
<a class="videoCall list-actions-action writeMessage" data-id="<%=id%>" href="#">Video call
' +
                    '
<a class="audioCall list-actions-action writeMessage" data-id="<%=id%>" href="#">Audio call
' +
                    '
<a class="list-actions-action writeMessage" data-id="<%=id%>" href="#">Write message
' +
                    '
<a class="list-actions-action userDetails" data-id="<%=id%>" href="#">Profile
';
            }

            return $html.append(_.template(htmlStr)(params));
        },

        getControlButtonsForPopupDetails: function(roster) {
            var $html = $('#popupDetails').find('.userDetails-controls'),
                htmlStr = '',
                params = {
                    roster: 'ask_subscription'
                };

            if (roster.subscription !== 'none' && roster.ask === null) {
                params.roster = '';
                htmlStr =
                    '
' +
                    '
' +
                    '
Make video call
' +
                    '
' +
                    '
' +
                    '
Make audio call
';
            }

            htmlStr += '<div class="btn_userDetails <%=roster%> writeMessage">' +
                '
' +
                '
Send message
' +
                '<div class="btn_userDetails <%=roster%> deleteContact">' +
                '
' +
                '
Remove contact and chat
';

            $html.empty();
            $html.append(_.template(htmlStr)(params));
        },

        profilePopover: function() {
            var html = $('
' +
                '
Profile
' +
                '
Settings
' +
                '
Log Out

');

            return html;
        }

    };

    QMHtml.Messages = {

        setMap: function(params) {
            var htmlTemplate = _.template(
                '<a class="open_map" href="<%=mapLink%>" target="_blank">' +
                '')(params);

            $('article#' + params.id).find('.message-geo')
                .addClass('with-geo')
                .append(htmlTemplate);
        },

        urlPreview: function(params) {
            var htmlTemplate = _.template(
                    '
<%=title%>
'+
                    '<%=description%>'+
                    '<% if (picture) { %>'+
                        '
'+
                            '<img src="<%=picture%>" alt="og_pic">'+
                        '
'+
                    '<% } %>'
                )(params);

            return htmlTemplate;
        }

    };

    QMHtml.Attach = {

        error: function(params) {
            var htmlTemplate = _.template('
'+
                ''+
                '
'+
                '
'+
                '
'+
                '
<%= errMsg %>
'+
                '

')(params);

            return htmlTemplate;
        },

        attach: function(params) {
            var htmlTemplate = _.template(
                '
' +
                '' +
                '' +
                '
' +
                '
' +
                '
' +
                '
<%= fileName %>
' +
                '<div id="progress_<%= id %>">
' +
                '<span class="attach-part attach-part_<%= id %>">' +
                ' of <%= fileSizeCrop %> <%= fileSizeUnit %>' +
                '

' +
                '<time class="message-time">Cancel</time>' +
                '

')(params);

            return htmlTemplate;
        }

    };

    return QMHtml;
});
<|endoftext|>


<commit_before>window.angular.module('Fahey').config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
	'use strict';

	$urlRouterProvider.otherwise('/wizard');

	$stateProvider
		.state('home', {
			url: '/home',
			templateUrl: 'views/home.html'
				//controller: 'adminController'
		})
		// https://scotch.io/tutorials/angularjs-multi-step-form-using-ui-router
		.state('wizard', {
			url: '/wizard',
			templateUrl: 'views/wizard/wizard.html',
			controller: 'WizardController'
		})
		.state('wizard.step1', {
            url: '/step1',
            templateUrl: 'views/wizard/step1.html'
        })
        .state('wizard.step2', {
            url: '/step2',
            templateUrl: 'views/wizard/step2.html'
        })
        .state('wizard.step3', {
            url: '/step3',
            templateUrl: 'views/wizard/step3.html'
        });
}]);
<commit_msg>reset home to default route<commit_after>window.angular.module('Fahey').config(['$stateProvider', '$urlRouterProvider', function ($stateProvider, $urlRouterProvider) {
	'use strict';

	$urlRouterProvider.otherwise('/home');

	$stateProvider
		.state('home', {
			url: '/home',
			templateUrl: 'views/home.html'
				//controller: 'adminController'
		})
		// https://scotch.io/tutorials/angularjs-multi-step-form-using-ui-router
		.state('wizard', {
			url: '/wizard',
			templateUrl: 'views/wizard/wizard.html',
			controller: 'WizardController'
		})
		.state('wizard.step1', {
            url: '/step1',
            templateUrl: 'views/wizard/step1.html'
        })
        .state('wizard.step2', {
            url: '/step2',
            templateUrl: 'views/wizard/step2.html'
        })
        .state('wizard.step3', {
            url: '/step3',
            templateUrl: 'views/wizard/step3.html'
        });
}]);
<|endoftext|>


<commit_before>'use strict';

/**
 * Configure the states of the application.
 */
angular.module('desecClientApp').config(function ($urlRouterProvider, $stateProvider, $translateProvider) {

	// available languages, first one is preferred
	var languages = ['en', 'de'];

	// preferred language
	$translateProvider
		.registerAvailableLanguageKeys(['en', 'de'], {
			'en_US': 'en',
			'en_UK': 'en',
			'en_AU': 'en',
			'en_NZ': 'en',
			'de_DE': 'de',
			'de_CH': 'de',
			'de_AT': 'de'
		})
		.determinePreferredLanguage();

	// set up translations
	angular.forEach(languages, function (lang) {
		$translateProvider.translations(lang, {
			'TITLE': 'This is ' + lang,
			'FOO': 'This is a ' + lang + ' paragraph'
		});
	});

	// Set up i18n root state
	$stateProvider.state('i18n', {
		template: '<ui-view/>',
		url: '/:lang',
		abstract: true,
		controller: function($translate, $stateParams) {
			$translate.use($stateParams.lang);
		}
	})

	$stateProvider

		.state('root', {
			url: '/',
			controller: function($translate, $state) {
				$state.go('i18n.home', {lang: $translate.preferredLanguage()});
			}
		})

		.state('i18n.home', {
			url: "/",
			templateUrl: "views/homepage.html"
		})

		.state('i18n.product', {
			url: '/product',
			template: '<ui-view/>'
		})

		.state('i18n.product.dyndns', {
			url: "/dyndns",
			templateUrl: "views/products/dyndns.html"
		})

	$urlRouterProvider.otherwise('/');

});
<commit_msg>feat(): introduced hashbang for all URLs<commit_after>'use strict';

/**
 * Configure the states of the application.
 */
angular.module('desecClientApp').config(function ($urlRouterProvider, $stateProvider, $translateProvider, $locationProvider) {

	// enable hashbang
	$locationProvider.hashPrefix('!');

	// available languages, first one is preferred
	var languages = ['en', 'de'];

	// preferred language
	$translateProvider
		.registerAvailableLanguageKeys(['en', 'de'], {
			'en_US': 'en',
			'en_UK': 'en',
			'en_AU': 'en',
			'en_NZ': 'en',
			'de_DE': 'de',
			'de_CH': 'de',
			'de_AT': 'de'
		})
		.determinePreferredLanguage();

	// set up translations
	angular.forEach(languages, function (lang) {
		$translateProvider.translations(lang, {
			'TITLE': 'This is ' + lang,
			'FOO': 'This is a ' + lang + ' paragraph'
		});
	});

	// Set up i18n root state
	$stateProvider.state('i18n', {
		template: '<ui-view/>',
		url: '/:lang',
		abstract: true,
		controller: function($translate, $stateParams) {
			$translate.use($stateParams.lang);
		}
	})

	$stateProvider

		.state('root', {
			url: '/',
			controller: function($translate, $state) {
				$state.go('i18n.home', {lang: $translate.preferredLanguage()});
			}
		})

		.state('i18n.home', {
			url: "/",
			templateUrl: "views/homepage.html"
		})

		.state('i18n.product', {
			url: '/product',
			template: '<ui-view/>'
		})

		.state('i18n.product.dyndns', {
			url: "/dyndns",
			templateUrl: "views/products/dyndns.html"
		})

	$urlRouterProvider.otherwise('/');

});
<|endoftext|>


<commit_before>'use strict';
var Token = function(contractAddress, userAddress, symbol, decimal, type) {
	this.contractAddress = contractAddress;
	this.userAddress = userAddress
	this.symbol = symbol;;
	this.decimal = decimal;
	this.type = type;
	this.balance = "loading";
}
Token.balanceHex = "0x70a08231";
Token.transferHex = "0xa9059cbb";
Token.popTokens = [{
	"address": "0x74c1e4b8cae59269ec1d85d3d4f324396048f4ac",
	"symbol": "BeerCoin 🍺 ",
	"decimal": 0,
	"type": "default"
},
{
  "address": "0xe4c94d45f7aef7018a5d66f44af780ec6023378e",
  "symbol": "CryptoCarbon",
  "decimal": 6,
  "type": "default"
},
{
	"address": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
	"symbol": "DAO",
	"decimal": 16,
	"type": "default"
},
{
	"address": "0x5c40eF6f527f4FbA68368774E6130cE6515123f2",
	"symbol": "DAO extraBalance",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a",
	"symbol": "DGD",
	"decimal": 9,
	"type": "default"
},
{
	"address": "0x54bda709fed875224eae569bb6817d96ef7ed9ad",
	"symbol": "DGDb",
	"decimal": 0,
	"type": "default"
},
{
  "address": "0xb582baaf5e749d6aa98a22355a9d08b4c4d013c8",
  "symbol": "HKG",
  "decimal": 18,
  "type": "default"
},
{
  "address": "0x888666CA69E0f178DED6D75b5726Cee99A87D698",
  "symbol": "ICN",
  "decimal": 18,
  "type": "default"
},
{
	"address": "0xc66ea802717bfb9833400264dd12c2bceaa34a6d",
	"symbol": "MKR",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0x45e42D659D9f9466cD5DF622506033145a9b89Bc",
	"symbol": "Nexium",
	"decimal": 3,
	"type": "default"
},
{
	"address": "0xD8912C10681D8B21Fd3742244f44658dBA12264E",
	"symbol": "PLU",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5",
	"symbol": "REP",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009",
	"symbol": "SNGLS",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7",
	"symbol": "Unicorn 🦄 ",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0x4DF812F6064def1e5e029f1ca858777CC98D2D81",
	"symbol": "XAUR",
	"decimal": 8,
	"type": "default"
}];
Token.prototype.getContractAddress = function() {
	return this.contractAddress;
}
Token.prototype.getUserAddress = function() {
	return this.userAddress;
}
Token.prototype.setUserAddress = function(address) {
	this.userAddress = address;
}
Token.prototype.getSymbol = function() {
	return this.symbol;
}
Token.prototype.getDecimal = function() {
	return this.decimal;
}
Token.prototype.getBalance = function() {
	return this.balance;
}
Token.prototype.getBalanceBN = function() {
	return this.balanceBN;
}
Token.prototype.setBalance = function() {
	var balanceCall = ethFuncs.getDataObj(this.contractAddress, Token.balanceHex, [ethFuncs.getNakedAddress(this.userAddress)]);
	var parentObj = this;
	ajaxReq.getEthCall(balanceCall, false, function(data) {
		try {
			if (!data.error) {
				parentObj.balance = new BigNumber(data.data).div(new BigNumber(10).pow(parentObj.getDecimal())).toString();
				parentObj.balanceBN = new BigNumber(data.data).toString();
			}
		} catch (e) {
			parentObj.balance = globalFuncs.errorMsgs[20];
            parentObj.balanceBN = '0';
		}
	});
}
Token.prototype.getData = function(toAdd, value) {
	try {
		if (!ethFuncs.validateEtherAddress(toAdd)) throw globalFuncs.errorMsgs[5];
		else if (!globalFuncs.isNumeric(value) || parseFloat(value) < 0) throw globalFuncs.errorMsgs[7];
		var value = ethFuncs.padLeft(new BigNumber(value).times(new BigNumber(10).pow(this.getDecimal())).toString(16), 64);
		var toAdd = ethFuncs.padLeft(ethFuncs.getNakedAddress(toAdd), 64);
		var data = Token.transferHex + toAdd + value;
		return {
			isError: false,
			data: data
		};
	} catch (e) {
		return {
			isError: true,
			error: e
		};
	}
}
module.exports = Token;
<commit_msg>change hkg tokens<commit_after>'use strict';
var Token = function(contractAddress, userAddress, symbol, decimal, type) {
	this.contractAddress = contractAddress;
	this.userAddress = userAddress
	this.symbol = symbol;;
	this.decimal = decimal;
	this.type = type;
	this.balance = "loading";
}
Token.balanceHex = "0x70a08231";
Token.transferHex = "0xa9059cbb";
Token.popTokens = [{
	"address": "0x74c1e4b8cae59269ec1d85d3d4f324396048f4ac",
	"symbol": "BeerCoin 🍺 ",
	"decimal": 0,
	"type": "default"
},
{
  "address": "0xe4c94d45f7aef7018a5d66f44af780ec6023378e",
  "symbol": "CryptoCarbon",
  "decimal": 6,
  "type": "default"
},
{
	"address": "0xbb9bc244d798123fde783fcc1c72d3bb8c189413",
	"symbol": "DAO",
	"decimal": 16,
	"type": "default"
},
{
	"address": "0x5c40eF6f527f4FbA68368774E6130cE6515123f2",
	"symbol": "DAO extraBalance",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0xe0b7927c4af23765cb51314a0e0521a9645f0e2a",
	"symbol": "DGD",
	"decimal": 9,
	"type": "default"
},
{
	"address": "0x54bda709fed875224eae569bb6817d96ef7ed9ad",
	"symbol": "DGDb",
	"decimal": 0,
	"type": "default"
},
{
  "address": "0xb582baaf5e749d6aa98a22355a9d08b4c4d013c8",
  "symbol": "HKG",
  "decimal": 3,
  "type": "default"
},
{
  "address": "0x888666CA69E0f178DED6D75b5726Cee99A87D698",
  "symbol": "ICN",
  "decimal": 18,
  "type": "default"
},
{
	"address": "0xc66ea802717bfb9833400264dd12c2bceaa34a6d",
	"symbol": "MKR",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0x45e42D659D9f9466cD5DF622506033145a9b89Bc",
	"symbol": "Nexium",
	"decimal": 3,
	"type": "default"
},
{
	"address": "0xD8912C10681D8B21Fd3742244f44658dBA12264E",
	"symbol": "PLU",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0x48c80F1f4D53D5951e5D5438B54Cba84f29F32a5",
	"symbol": "REP",
	"decimal": 18,
	"type": "default"
},
{
	"address": "0xaec2e87e0a235266d9c5adc9deb4b2e29b54d009",
	"symbol": "SNGLS",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0x89205A3A3b2A69De6Dbf7f01ED13B2108B2c43e7",
	"symbol": "Unicorn 🦄 ",
	"decimal": 0,
	"type": "default"
},
{
	"address": "0x4DF812F6064def1e5e029f1ca858777CC98D2D81",
	"symbol": "XAUR",
	"decimal": 8,
	"type": "default"
}];
Token.prototype.getContractAddress = function() {
	return this.contractAddress;
}
Token.prototype.getUserAddress = function() {
	return this.userAddress;
}
Token.prototype.setUserAddress = function(address) {
	this.userAddress = address;
}
Token.prototype.getSymbol = function() {
	return this.symbol;
}
Token.prototype.getDecimal = function() {
	return this.decimal;
}
Token.prototype.getBalance = function() {
	return this.balance;
}
Token.prototype.getBalanceBN = function() {
	return this.balanceBN;
}
Token.prototype.setBalance = function() {
	var balanceCall = ethFuncs.getDataObj(this.contractAddress, Token.balanceHex, [ethFuncs.getNakedAddress(this.userAddress)]);
	var parentObj = this;
	ajaxReq.getEthCall(balanceCall, false, function(data) {
		try {
			if (!data.error) {
				parentObj.balance = new BigNumber(data.data).div(new BigNumber(10).pow(parentObj.getDecimal())).toString();
				parentObj.balanceBN = new BigNumber(data.data).toString();
			}
		} catch (e) {
			parentObj.balance = globalFuncs.errorMsgs[20];
            parentObj.balanceBN = '0';
		}
	});
}
Token.prototype.getData = function(toAdd, value) {
	try {
		if (!ethFuncs.validateEtherAddress(toAdd)) throw globalFuncs.errorMsgs[5];
		else if (!globalFuncs.isNumeric(value) || parseFloat(value) < 0) throw globalFuncs.errorMsgs[7];
		var value = ethFuncs.padLeft(new BigNumber(value).times(new BigNumber(10).pow(this.getDecimal())).toString(16), 64);
		var toAdd = ethFuncs.padLeft(ethFuncs.getNakedAddress(toAdd), 64);
		var data = Token.transferHex + toAdd + value;
		return {
			isError: false,
			data: data
		};
	} catch (e) {
		return {
			isError: true,
			error: e
		};
	}
}
module.exports = Token;
<|endoftext|>


<commit_before>define((require, exports, module)=>{
  const koru            = require('koru');
  require('koru/server');
  const StackErrorConvert = require('koru/stack-error-convert');
  const UserAccount     = require('koru/user-account');
  const Ranking         = require('models/ranking');
  const EventPub        = require('pubsub/event-pub');
  const OrgPub          = require('pubsub/org-pub');
  const SelfPub         = require('pubsub/self-pub');

  require('models/reg-upload-server');

  console.log(`org-node KORU_APP_VERSION = `+process.env.KORU_APP_VERSION);
  if (process.env.KORU_APP_VERSION !== undefined) {
    StackErrorConvert.start({sourceMapDir: '../build', lineAdjust: -1});
  }

  const emailConfig = koru.config.userAccount.emailConfig;
  emailConfig.sendResetPasswordEmailText = (user, resetToken)=> require('server/email-text')
    .sendResetPasswordEmailText(user, resetToken);

  module.onUnload((mod, error)=>{
    if (error) return;
    const modId = mod.id;
    setTimeout(()=>{
      require(modId, sc =>{sc.start && sc.start()});
    });
  });

  return ()=>{
    require('koru/email').initPool(koru.config.mailUrl);
    UserAccount.init();
  };
});
<commit_msg>fix stack traces for new bundle method<commit_after>define((require, exports, module)=>{
  const koru            = require('koru');
  require('koru/server');
  const StackErrorConvert = require('koru/stack-error-convert');
  const UserAccount     = require('koru/user-account');
  const Ranking         = require('models/ranking');
  const EventPub        = require('pubsub/event-pub');
  const OrgPub          = require('pubsub/org-pub');
  const SelfPub         = require('pubsub/self-pub');

  require('models/reg-upload-server');

  console.log(`org-node KORU_APP_VERSION = `+process.env.KORU_APP_VERSION);
  if (process.env.KORU_APP_VERSION !== void 0) {
    StackErrorConvert.start({sourceMapDir: '../build'});
  }

  const emailConfig = koru.config.userAccount.emailConfig;
  emailConfig.sendResetPasswordEmailText = (user, resetToken)=> require('server/email-text')
    .sendResetPasswordEmailText(user, resetToken);

  module.onUnload((mod, error)=>{
    if (error) return;
    const modId = mod.id;
    setTimeout(()=>{
      require(modId, sc =>{sc.start && sc.start()});
    });
  });

  return ()=>{
    require('koru/email').initPool(koru.config.mailUrl);
    UserAccount.init();
  };
});
<|endoftext|>


<commit_before>var app = angular.module('SpfyApp', [])

app.controller('SpfyController', [
    '$scope',
    '$log',
    '$http',
    '$timeout',
    function($scope, $log, $http, $timeout) {

        $scope.loading = false;
        $scope.urlerror = false;

        $scope.jobfailed = false;
        $scope.message='';

        // for table sort/search
        $scope.sortType     = 'filename'; // set the default sort type
        $scope.sortReverse  = false;  // set the default sort order

        // define form in scope
        $scope.formData={};
        // set defaults
        $scope.formData.options={};
        $scope.formData.options.vf=true
        $scope.formData.options.amr=true
        $scope.formData.options.serotype=true
        $scope.formData.options.pi=90

        var fd = new FormData();

        $scope.getTheFiles = function ($files) {
                angular.forEach($files, function (value, key) {
                    fd.append('file', value);
                });
            };

        $scope.getResults = function() {

            // get the URL from the input
            //var userInput = $scope.myFile;

            // fire the API request

            //fd.append('file', userInput);
            fd.append('options.vf', $scope.formData.options.vf);
            fd.append('options.amr', $scope.formData.options.amr);
            fd.append('options.serotype', $scope.formData.options.serotype);
            fd.append('options.pi', $scope.formData.options.pi);
            $log.log(fd);
            $http.post('/upload', fd, {
                transformRequest: angular.identity,
                headers: {
                    'Content-Type': undefined
                }
            }).success(function(results) {
                $log.log(results);
                $scope.spits = [];
                getSpfySpit(results);
                $scope.loading = true;
                $scope.urlerror = false;
                //will have to add this in server resp
                //$scope.message = data.message;
            }).error(function(error) {
                $log.log(error);
            });

        };

        function getSpfySpit(results) {

            var timeout = '';

            var poller = function(key) {
                // fire another request
                if (key !== undefined) {
                    $http.get('/results/' + key).success(function(data, status, headers, config) {
                        if (status == 200) {
                            $log.log(data);
                            $scope.loading = false;
                            $scope.spits = $scope.spits.concat(data);
                            $log.log($scope.spits)
                            $timeout.cancel(timeout);
                            return false;
                        } else if (status == 202){
                          // job result not found ie. still pending
                          $scope.loading = true;
                        } else if (status == 415){
                          // got some message (eg. a failed job)
                          $scope.jobfailed = true;
                          $scope.message = $scope.message + ('Job ' + key ' has failed.');
                          $scope.loading = false;
                        }
                        // continue to call the poller() function every 2 seconds
                        // until the timeout is cancelled
                        timeout = $timeout(poller(key), 2000);
                    }).error(function(error) {
                        $log.log(error);
                        $scope.loading = false;
                        $scope.urlerror = true;

                    });
                };

            }

            angular.forEach(results, function(value, key) {
                $log.log(value, key);
                poller(key)
            });

        }

    }
])

app.directive('fileModel', [
    '$parse',
    function($parse) {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                var model = $parse(attrs.fileModel);
                var modelSetter = model.assign;

                element.bind('change', function() {
                    scope.$apply(function() {
                        modelSetter(scope, element[0].files[0]);
                    });
                });
            }
        };
    }
]);

app.directive('exportToCsv', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var el = element[0];
            element.bind('click', function(e) {
                var table = e.target.nextElementSibling;
                var csvString = '';
                for (var i = 0; i < table.rows.length; i++) {
                    var rowData = table.rows[i].cells;
                    for (var j = 0; j < rowData.length; j++) {
                        csvString = csvString + rowData[j].textContent.trim() + ",";
                    }
                    csvString = csvString.substring(0, csvString.length - 1);
                    csvString = csvString + "\n";
                }
                csvString = csvString.substring(0, csvString.length - 1);
                var a = $('<a/>', {
                    style: 'display:none',
                    href: 'data:application/octet-stream;base64,' + btoa(csvString),
                    download: 'results.csv'
                }).appendTo('body')
                a[0].click()
                a.remove();
            });
        }
    }
});

app.directive('ngFiles', ['$parse', function ($parse) {

            function fn_link(scope, element, attrs) {
                var onChange = $parse(attrs.ngFiles);
                element.on('change', function (event) {
                    onChange(scope, { $files: event.target.files });
                });
            };

            return {
                link: fn_link
            }
        } ])
<commit_msg>syntax<commit_after>var app = angular.module('SpfyApp', [])

app.controller('SpfyController', [
    '$scope',
    '$log',
    '$http',
    '$timeout',
    function($scope, $log, $http, $timeout) {

        $scope.loading = false;
        $scope.urlerror = false;

        $scope.jobfailed = false;
        $scope.message='';

        // for table sort/search
        $scope.sortType     = 'filename'; // set the default sort type
        $scope.sortReverse  = false;  // set the default sort order

        // define form in scope
        $scope.formData={};
        // set defaults
        $scope.formData.options={};
        $scope.formData.options.vf=true
        $scope.formData.options.amr=true
        $scope.formData.options.serotype=true
        $scope.formData.options.pi=90

        var fd = new FormData();

        $scope.getTheFiles = function ($files) {
                angular.forEach($files, function (value, key) {
                    fd.append('file', value);
                });
            };

        $scope.getResults = function() {

            // get the URL from the input
            //var userInput = $scope.myFile;

            // fire the API request

            //fd.append('file', userInput);
            fd.append('options.vf', $scope.formData.options.vf);
            fd.append('options.amr', $scope.formData.options.amr);
            fd.append('options.serotype', $scope.formData.options.serotype);
            fd.append('options.pi', $scope.formData.options.pi);
            $log.log(fd);
            $http.post('/upload', fd, {
                transformRequest: angular.identity,
                headers: {
                    'Content-Type': undefined
                }
            }).success(function(results) {
                $log.log(results);
                $scope.spits = [];
                getSpfySpit(results);
                $scope.loading = true;
                $scope.urlerror = false;
                //will have to add this in server resp
                //$scope.message = data.message;
            }).error(function(error) {
                $log.log(error);
            });

        };

        function getSpfySpit(results) {

            var timeout = '';

            var poller = function(key) {
                // fire another request
                if (key !== undefined) {
                    $http.get('/results/' + key).success(function(data, status, headers, config) {
                        if (status == 200) {
                            $log.log(data);
                            $scope.loading = false;
                            $scope.spits = $scope.spits.concat(data);
                            $log.log($scope.spits)
                            $timeout.cancel(timeout);
                            return false;
                        } else if (status == 202){
                          // job result not found ie. still pending
                          $scope.loading = true;
                        } else if (status == 415){
                          // got some message (eg. a failed job)
                          $scope.jobfailed = true;
                          $scope.message = $scope.message + 'Job ' + key ' has failed.';
                          $scope.loading = false;
                        }
                        // continue to call the poller() function every 2 seconds
                        // until the timeout is cancelled
                        timeout = $timeout(poller(key), 2000);
                    }).error(function(error) {
                        $log.log(error);
                        $scope.loading = false;
                        $scope.urlerror = true;

                    });
                };

            }

            angular.forEach(results, function(value, key) {
                $log.log(value, key);
                poller(key)
            });

        }

    }
])

app.directive('fileModel', [
    '$parse',
    function($parse) {
        return {
            restrict: 'A',
            link: function(scope, element, attrs) {
                var model = $parse(attrs.fileModel);
                var modelSetter = model.assign;

                element.bind('change', function() {
                    scope.$apply(function() {
                        modelSetter(scope, element[0].files[0]);
                    });
                });
            }
        };
    }
]);

app.directive('exportToCsv', function() {
    return {
        restrict: 'A',
        link: function(scope, element, attrs) {
            var el = element[0];
            element.bind('click', function(e) {
                var table = e.target.nextElementSibling;
                var csvString = '';
                for (var i = 0; i < table.rows.length; i++) {
                    var rowData = table.rows[i].cells;
                    for (var j = 0; j < rowData.length; j++) {
                        csvString = csvString + rowData[j].textContent.trim() + ",";
                    }
                    csvString = csvString.substring(0, csvString.length - 1);
                    csvString = csvString + "\n";
                }
                csvString = csvString.substring(0, csvString.length - 1);
                var a = $('<a/>', {
                    style: 'display:none',
                    href: 'data:application/octet-stream;base64,' + btoa(csvString),
                    download: 'results.csv'
                }).appendTo('body')
                a[0].click()
                a.remove();
            });
        }
    }
});

app.directive('ngFiles', ['$parse', function ($parse) {

            function fn_link(scope, element, attrs) {
                var onChange = $parse(attrs.ngFiles);
                element.on('change', function (event) {
                    onChange(scope, { $files: event.target.files });
                });
            };

            return {
                link: fn_link
            }
        } ])
<|endoftext|>