<commit_before>import * as doms from 'shared/utils/dom';

const SCROLL_DELTA_X = 48;
const SCROLL_DELTA_Y = 48;

// dirty way to store scrolling state on globally
let scrolling = false;
let lastTimeoutId = null;

const isScrollableStyle = (element) => {
  let { overflowX, overflowY } = window.getComputedStyle(element);
  return !(overflowX !== 'scroll' && overflowX !== 'auto' &&
    overflowY !== 'scroll' && overflowY !== 'auto');
};

const isOverflowed = (element) => {
  return element.scrollWidth > element.clientWidth ||
    element.scrollHeight > element.clientHeight;
};

// Find a visiable and scrollable element by depth-first search.  Currently
// this method is called by each scrolling, and the returned value of this
// method is not cached.  That does not cause performance issue because in the
// most pages, the window is root element i,e, documentElement.
const findScrollable = (element) => {
  if (isScrollableStyle(element) && isOverflowed(element)) {
    return element;
  }

  let children = Array.from(element.children).filter(doms.isVisible);
  for (let child of children) {
    let scrollable = findScrollable(child);
    if (scrollable) {
      return scrollable;
    }
  }
  return null;
};

const scrollTarget = () => {
  if (isOverflowed(window.document.documentElement)) {
    return window.document.documentElement;
  }
  if (isOverflowed(window.document.body)) {
    return window.document.body;
  }
  let target = findScrollable(window.document.documentElement);
  if (target) {
    return target;
  }
  return window.document.documentElement;
};

const resetScrolling = () => {
  scrolling = false;
};

class SmoothScroller {
  constructor(element) {
    this.element = element;
  }

  scroll(x, y) {
    window.scrollTo({
      left: x,
      top: y,
      behavior: 'smooth',
    });
    scrolling = true;
    if (lastTimeoutId) {
      clearTimeout(lastTimeoutId);
      lastTimeoutId = null;
    }
    lastTimeoutId = setTimeout(resetScrolling, 100);
  }
}

class RoughtScroller {
  constructor(element) {
    this.element = element;
  }

  scroll(x, y) {
    this.element.scrollTo(x, y);
  }
}

const scroller = (element, smooth) => {
  if (smooth) {
    return new SmoothScroller(element);
  }
  return new RoughtScroller(element);
};

const getScroll = () => {
  let target = scrollTarget();
  return { x: target.scrollLeft, y: target.scrollTop };
};

const scrollVertically = (count, smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft;
  let y = target.scrollTop + SCROLL_DELTA_Y * count;
  if (scrolling) {
    y = target.scrollTop + SCROLL_DELTA_Y * count * 4;
  }
  scroller(target, smooth).scroll(x, y);
};

const scrollHorizonally = (count, smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft + SCROLL_DELTA_X * count;
  let y = target.scrollTop;
  if (scrolling) {
    y = target.scrollTop + SCROLL_DELTA_Y * count * 4;
  }
  scroller(target, smooth).scroll(x, y);
};

const scrollPages = (count, smooth) => {
  let target = scrollTarget();
  let height = target.clientHeight;
  let x = target.scrollLeft;
  let y = target.scrollTop + height * count;
  if (scrolling) {
    y = target.scrollTop + height * count * 4;
  }
  scroller(target, smooth).scroll(x, y);
};

const scrollTo = (x, y, smooth) => {
  let target = scrollTarget();
  scroller(target, smooth, false).scroll(x, y);
};

const scrollToTop = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft;
  let y = 0;
  scroller(target, smooth, false).scroll(x, y);
};

const scrollToBottom = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft;
  let y = target.scrollHeight;
  scroller(target, smooth, false).scroll(x, y);
};

const scrollToHome = (smooth) => {
  let target = scrollTarget();
  let x = 0;
  let y = target.scrollTop;
  scroller(target, smooth, false).scroll(x, y);
};

const scrollToEnd = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollWidth;
  let y = target.scrollTop;
  scroller(target, smooth, false).scroll(x, y);
};

export {
  getScroll,
  scrollVertically, scrollHorizonally, scrollPages,
  scrollTo,
  scrollToTop, scrollToBottom, scrollToHome, scrollToEnd
};
<commit_msg>Clean scroller<commit_after>import * as doms from 'shared/utils/dom';

const SCROLL_DELTA_X = 48;
const SCROLL_DELTA_Y = 48;

// dirty way to store scrolling state on globally
let scrolling = false;
let lastTimeoutId = null;

const isScrollableStyle = (element) => {
  let { overflowX, overflowY } = window.getComputedStyle(element);
  return !(overflowX !== 'scroll' && overflowX !== 'auto' &&
    overflowY !== 'scroll' && overflowY !== 'auto');
};

const isOverflowed = (element) => {
  return element.scrollWidth > element.clientWidth ||
    element.scrollHeight > element.clientHeight;
};

// Find a visiable and scrollable element by depth-first search.  Currently
// this method is called by each scrolling, and the returned value of this
// method is not cached.  That does not cause performance issue because in the
// most pages, the window is root element i,e, documentElement.
const findScrollable = (element) => {
  if (isScrollableStyle(element) && isOverflowed(element)) {
    return element;
  }

  let children = Array.from(element.children).filter(doms.isVisible);
  for (let child of children) {
    let scrollable = findScrollable(child);
    if (scrollable) {
      return scrollable;
    }
  }
  return null;
};

const scrollTarget = () => {
  if (isOverflowed(window.document.documentElement)) {
    return window.document.documentElement;
  }
  if (isOverflowed(window.document.body)) {
    return window.document.body;
  }
  let target = findScrollable(window.document.documentElement);
  if (target) {
    return target;
  }
  return window.document.documentElement;
};

const resetScrolling = () => {
  scrolling = false;
};

class Scroller {
  constructor(element, smooth) {
    this.element = element;
    this.smooth = smooth;
  }

  scrollTo(x, y) {
    let behavior = this.smooth ? 'smooth' : 'auto';
    window.scrollTo({
      left: x,
      top: y,
      behavior: behavior,
    });
    if (!this.smooth) {
      return;
    }
    this.prepareReset();
  }

  scrollBy(x, y) {
    let behavior = this.smooth ? 'smooth' : 'auto';
    window.scrollBy({
      left: x,
      top: y,
      behavior: behavior,
    });
    if (!this.smooth) {
      return;
    }
    this.prepareReset();
  }

  prepareReset() {
    scrolling = true;
    if (lastTimeoutId) {
      clearTimeout(lastTimeoutId);
      lastTimeoutId = null;
    }
    lastTimeoutId = setTimeout(resetScrolling, 100);
  }
}

class RoughtScroller {
  constructor(element) {
    this.element = element;
  }

  scroll(x, y) {
    this.element.scrollTo(x, y);
  }
}

const getScroll = () => {
  let target = scrollTarget();
  return { x: target.scrollLeft, y: target.scrollTop };
};

const scrollVertically = (count, smooth) => {
  let target = scrollTarget();
  let delta = SCROLL_DELTA_Y * count;
  if (scrolling) {
    delta = SCROLL_DELTA_Y * count * 4;
  }
  new Scroller(target, smooth).scrollBy(0, delta);
};

const scrollHorizonally = (count, smooth) => {
  let target = scrollTarget();
  let delta = SCROLL_DELTA_X * count;
  if (scrolling) {
    delta = SCROLL_DELTA_X * count * 4;
  }
  new Scroller(target, smooth).scrollBy(delta, 0);
};

const scrollPages = (count, smooth) => {
  let target = scrollTarget();
  let height = target.clientHeight;
  let delta = height * count;
  if (scrolling) {
    delta = height * count;
  }
  new Scroller(target, smooth).scrollBy(0, delta);
};

const scrollTo = (x, y, smooth) => {
  let target = scrollTarget();
  new Scroller(target, smooth).scrollTo(x, y);
};

const scrollToTop = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft;
  let y = 0;
  new Scroller(target, smooth).scrollTo(x, y);
};

const scrollToBottom = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollLeft;
  let y = target.scrollHeight;
  new Scroller(target, smooth).scrollTo(x, y);
};

const scrollToHome = (smooth) => {
  let target = scrollTarget();
  let x = 0;
  let y = target.scrollTop;
  new Scroller(target, smooth).scrollTo(x, y);
};

const scrollToEnd = (smooth) => {
  let target = scrollTarget();
  let x = target.scrollWidth;
  let y = target.scrollTop;
  new Scroller(target, smooth).scrollTo(x, y);
};

export {
  getScroll,
  scrollVertically, scrollHorizonally, scrollPages,
  scrollTo,
  scrollToTop, scrollToBottom, scrollToHome, scrollToEnd
};
<|endoftext|>


<commit_before>const url = require('url');
const WebSocket = require('ws');

var fs = require('fs'); // Node.js File System

const Rooms = require('./rooms');

// Enum of game modes.
var Mode = {
    START_ROOM: 1,
    JOIN_ROOM: 2,
    JOIN_RANDOM: 3,
};

var wss;

/* Initializes the WebSocket on the given server. */
function start(server) {
	wss = new WebSocket.Server({ server, perMessageDeflate: false });
	wss.on('connection', onConnection);
}

/* Called when a client connects to the WebSocket. */
function onConnection(client) {
	// Set the event listeners.
	client.on('message', function(message) {onIncomingMessage(message, client)});
	client.on('close', onClose);

	client.send('Connection opened.');
}

/* Called when the server receives a message from a client. */
function onIncomingMessage(message, client) {
	try {
		// First try parsing the data as JSON.
		var json = JSON.parse(message);
		handleClientJson(client, json);
	} catch (error) {
		if (error instanceof SyntaxError) {
			// If it's not JSON, just broadcast the message.
			broadcastText(client, message);
		} else {
			// If the message was JSON, but an unrelated error happened.
			throw error;
		}
	}
}

/* Handle JSON sent from a client. */
function handleClientJson(client, json) {
	if (json.mode) {
        if (json.mode == Mode.START_ROOM) {
            startRoomWithFriends(client);
		} else if (json.mode == Mode.JOIN_ROOM) {
            joinRoomWithFriends(client, json.roomCode);
		} else if (json.mode == Mode.JOIN_RANDOM) {
            joinRandom(client);
		}
	}

    if (json.hasOwnProperty('readyToVote')) {
        Rooms.setPlayerAsReady(client, json.readyToVote);
    }

    if (json.ballot) {
        Rooms.submitBallot(client, json.ballot);
    }

	if (json.message) {
		broadcastText(client, json.message);
	}
}

/* Broadcast text to all the clients in the sender's room. */
function broadcastText(sender, message) {
    var room = Rooms.getRoomOfClient(sender);
	room.broadcast(message, sender);
    fs.appendFile('./game/bots/recentmessages.txt', message + '\n', 'utf8');
}

/* Called when a client closes the WebSocket connection. */
function onClose(code, reason) {
    console.log("A client disconnected. Code: " + code + ". Reason: " + reason);
    // Unfortunately, we cannot tell which client disconnected.
}

function joinRandom(client) {
    // Keep track of the newly joined client.
    var room = Rooms.getWaitingRoom();
	Rooms.addClientToRoom(client, room);
}

function startRoomWithFriends(client) {
    var code = Rooms.newRoomCode();
    var room = Rooms.getRoomByCode(code);
    Rooms.addClientToRoom(client, room);
    sendCodeToClient(code, client);
}

function sendCodeToClient(code, client) {
    var payload = {'roomCode': code};
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(payload));
    }
}

function joinRoomWithFriends(client, roomCode) {
    if (Rooms.validCode(roomCode)) {
        var room = Rooms.getRoomByCode(roomCode);
        Rooms.addClientToRoom(client, room);
        sendJoinReceipt(client);
    } else {
        // If we can't find the room, display an error to the user.
        clientError(client, "That room does not exist.");
    }
}

// Tell the client that they have successfully joined a room.
function sendJoinReceipt(client) {
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({"joinedRoom": true}));
    }
}

function clientError(client, message) {
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({"error": message}));
    }
}

module.exports = {start: start};
<commit_msg>Remove a client from their room when they disconnect from the websocket connection.<commit_after>const url = require('url');
const WebSocket = require('ws');

var fs = require('fs'); // Node.js File System

const Rooms = require('./rooms');

// Enum of game modes.
var Mode = {
    START_ROOM: 1,
    JOIN_ROOM: 2,
    JOIN_RANDOM: 3,
};

var wss;

/* Initializes the WebSocket on the given server. */
function start(server) {
	wss = new WebSocket.Server({ server, perMessageDeflate: false });
	wss.on('connection', onConnection);
}

/* Called when a client connects to the WebSocket. */
function onConnection(client) {
	// Set the event listeners.
	client.on('message', function(message) {onIncomingMessage(message, client)});
	client.on('close', function(code, reason) {onClose(code, reason, client)});

	client.send('Connection opened.');
}

/* Called when the server receives a message from a client. */
function onIncomingMessage(message, client) {
	try {
		// First try parsing the data as JSON.
		var json = JSON.parse(message);
		handleClientJson(client, json);
	} catch (error) {
		if (error instanceof SyntaxError) {
			// If it's not JSON, just broadcast the message.
			broadcastText(client, message);
		} else {
			// If the message was JSON, but an unrelated error happened.
			throw error;
		}
	}
}

/* Handle JSON sent from a client. */
function handleClientJson(client, json) {
	if (json.mode) {
        if (json.mode == Mode.START_ROOM) {
            startRoomWithFriends(client);
		} else if (json.mode == Mode.JOIN_ROOM) {
            joinRoomWithFriends(client, json.roomCode);
		} else if (json.mode == Mode.JOIN_RANDOM) {
            joinRandom(client);
		}
	}

    if (json.hasOwnProperty('readyToVote')) {
        Rooms.setPlayerAsReady(client, json.readyToVote);
    }

    if (json.ballot) {
        Rooms.submitBallot(client, json.ballot);
    }

	if (json.message) {
		broadcastText(client, json.message);
	}
}

/* Broadcast text to all the clients in the sender's room. */
function broadcastText(sender, message) {
    var room = Rooms.getRoomOfClient(sender);
	room.broadcast(message, sender);
    fs.appendFile('./game/bots/recentmessages.txt', message + '\n', 'utf8');
}

/* Called when a client closes the WebSocket connection. */
function onClose(code, reason, sender) {
    var room = Rooms.getRoomOfClient(sender);
    room.remove(sender);
    console.log("A client disconnected. Code: " + code + ". Reason: " + reason);
}

function joinRandom(client) {
    // Keep track of the newly joined client.
    var room = Rooms.getWaitingRoom();
	Rooms.addClientToRoom(client, room);
}

function startRoomWithFriends(client) {
    var code = Rooms.newRoomCode();
    var room = Rooms.getRoomByCode(code);
    Rooms.addClientToRoom(client, room);
    sendCodeToClient(code, client);
}

function sendCodeToClient(code, client) {
    var payload = {'roomCode': code};
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(payload));
    }
}

function joinRoomWithFriends(client, roomCode) {
    if (Rooms.validCode(roomCode)) {
        var room = Rooms.getRoomByCode(roomCode);
        Rooms.addClientToRoom(client, room);
        sendJoinReceipt(client);
    } else {
        // If we can't find the room, display an error to the user.
        clientError(client, "That room does not exist.");
    }
}

// Tell the client that they have successfully joined a room.
function sendJoinReceipt(client) {
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({"joinedRoom": true}));
    }
}

function clientError(client, message) {
    if (client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify({"error": message}));
    }
}

module.exports = {start: start};
<|endoftext|>


<commit_before>/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Popup/Framed.js
 * @requires OpenLayers/Util.js
 */

/**
 * Class: OpenLayers.Popup.FramedCloud
 *
 * Inherits from:
 *  - <OpenLayers.Popup.Framed>
 */
OpenLayers.Popup.FramedCloud =
  OpenLayers.Class(OpenLayers.Popup.Framed, {

    /**
     * Property: contentDisplayClass
     * {String} The CSS class of the popup content div.
     */
    contentDisplayClass: "olFramedCloudPopupContent",

    /**
     * APIProperty: autoSize
     * {Boolean} Framed Cloud is autosizing by default.
     */
    autoSize: true,

    /**
     * APIProperty: panMapIfOutOfView
     * {Boolean} Framed Cloud does pan into view by default.
     */
    panMapIfOutOfView: true,

    /**
     * APIProperty: imageSize
     * {<OpenLayers.Size>}
     */
    imageSize: new OpenLayers.Size(676, 736),

    /**
     * APIProperty: isAlphaImage
     * {Boolean} The FramedCloud does not use an alpha image (in honor of the
     *     good ie6 folk out there)
     */
    isAlphaImage: false,

    /**
     * APIProperty: fixedRelativePosition
     * {Boolean} The Framed Cloud popup works in just one fixed position.
     */
    fixedRelativePosition: false,

    /**
     * Property: positionBlocks
     * {Object} Hash of differen position blocks, keyed by relativePosition
     *     two-character code string (ie "tl", "tr", "bl", "br")
     */
    positionBlocks: {
        "tl": {
            'offset': new OpenLayers.Pixel(44, 0),
            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 32, 80, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 54),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(0, -668)
                }
            ]
        },
        "tr": {
            'offset': new OpenLayers.Pixel(-45, 0),
            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 32, 22, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 54),
                    anchor: new OpenLayers.Bounds(0, 0, null, null),
                    position: new OpenLayers.Pixel(-215, -668)
                }
            ]
        },
        "bl": {
            'offset': new OpenLayers.Pixel(45, 0),
            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 54),
                    anchor: new OpenLayers.Bounds(null, null, 0, 0),
                    position: new OpenLayers.Pixel(-101, -674)
                }
            ]
        },
        "br": {
            'offset': new OpenLayers.Pixel(-44, 0),
            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 54),
                    anchor: new OpenLayers.Bounds(0, null, null, 0),
                    position: new OpenLayers.Pixel(-311, -674)
                }
            ]
        }
    },

    /**
     * APIProperty: minSize
     * {<OpenLayers.Size>}
     */
    minSize: new OpenLayers.Size(105, 10),

    /**
     * APIProperty: maxSize
     * {<OpenLayers.Size>}
     */
    maxSize: new OpenLayers.Size(600, 660),

    /**
     * Constructor: OpenLayers.Popup.FramedCloud
     *
     * Parameters:
     * id - {String}
     * lonlat - {<OpenLayers.LonLat>}
     * contentSize - {<OpenLayers.Size>}
     * contentHTML - {String}
     * anchor - {Object} Object to which we'll anchor the popup. Must expose
     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)
     *     (Note that this is generally an <OpenLayers.Icon>).
     * closeBox - {Boolean}
     * closeBoxCallback - {Function} Function to be called on closeBox click.
     */
    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
                        closeBoxCallback) {

        this.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.png';
        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments);
        this.contentDiv.className = this.contentDisplayClass;
    },

    /**
     * APIMethod: destroy
     */
    destroy: function() {
        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Popup.FramedCloud"
});
<commit_msg>Fix broken positionBlocks, which cuased overlaps. This is neccesary to easily handle semi-transparent alternatives to the main framedcloud image.<commit_after>/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
 * license.  See http://svn.openlayers.org/trunk/openlayers/license.txt for the
 * full text of the license. */

/**
 * @requires OpenLayers/Popup/Framed.js
 * @requires OpenLayers/Util.js
 */

/**
 * Class: OpenLayers.Popup.FramedCloud
 *
 * Inherits from:
 *  - <OpenLayers.Popup.Framed>
 */
OpenLayers.Popup.FramedCloud =
  OpenLayers.Class(OpenLayers.Popup.Framed, {

    /**
     * Property: contentDisplayClass
     * {String} The CSS class of the popup content div.
     */
    contentDisplayClass: "olFramedCloudPopupContent",

    /**
     * APIProperty: autoSize
     * {Boolean} Framed Cloud is autosizing by default.
     */
    autoSize: true,

    /**
     * APIProperty: panMapIfOutOfView
     * {Boolean} Framed Cloud does pan into view by default.
     */
    panMapIfOutOfView: true,

    /**
     * APIProperty: imageSize
     * {<OpenLayers.Size>}
     */
    imageSize: new OpenLayers.Size(676, 736),

    /**
     * APIProperty: isAlphaImage
     * {Boolean} The FramedCloud does not use an alpha image (in honor of the
     *     good ie6 folk out there)
     */
    isAlphaImage: false,

    /**
     * APIProperty: fixedRelativePosition
     * {Boolean} The Framed Cloud popup works in just one fixed position.
     */
    fixedRelativePosition: false,

    /**
     * Property: positionBlocks
     * {Object} Hash of differen position blocks, keyed by relativePosition
     *     two-character code string (ie "tl", "tr", "bl", "br")
     */
    positionBlocks: {
        "tl": {
            'offset': new OpenLayers.Pixel(44, 0),
            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 19),
                    anchor: new OpenLayers.Bounds(0, 32, 22, null),
                    position: new OpenLayers.Pixel(0, -631)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 18),
                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
                    position: new OpenLayers.Pixel(-638, -632)
                },
                { // stem
                    size: new OpenLayers.Size(81, 35),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(0, -688)
                }
            ]
        },
        "tr": {
            'offset': new OpenLayers.Pixel(-45, 0),
            'padding': new OpenLayers.Bounds(8, 40, 8, 9),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 51, 22, 0),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 50, 0, 0),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 19),
                    anchor: new OpenLayers.Bounds(0, 32, 22, null),
                    position: new OpenLayers.Pixel(0, -631)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 19),
                    anchor: new OpenLayers.Bounds(null, 32, 0, null),
                    position: new OpenLayers.Pixel(-638, -631)
                },
                { // stem
                    size: new OpenLayers.Size(81, 35),
                    anchor: new OpenLayers.Bounds(0, 0, null, null),
                    position: new OpenLayers.Pixel(-215, -687)
                }
            ]
        },
        "bl": {
            'offset': new OpenLayers.Pixel(45, 0),
            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 33),
                    anchor: new OpenLayers.Bounds(null, null, 0, 0),
                    position: new OpenLayers.Pixel(-101, -674)
                }
            ]
        },
        "br": {
            'offset': new OpenLayers.Pixel(-44, 0),
            'padding': new OpenLayers.Bounds(8, 9, 8, 40),
            'blocks': [
                { // top-left
                    size: new OpenLayers.Size('auto', 'auto'),
                    anchor: new OpenLayers.Bounds(0, 21, 22, 32),
                    position: new OpenLayers.Pixel(0, 0)
                },
                { //top-right
                    size: new OpenLayers.Size(22, 'auto'),
                    anchor: new OpenLayers.Bounds(null, 21, 0, 32),
                    position: new OpenLayers.Pixel(-638, 0)
                },
                { //bottom-left
                    size: new OpenLayers.Size('auto', 21),
                    anchor: new OpenLayers.Bounds(0, 0, 22, null),
                    position: new OpenLayers.Pixel(0, -629)
                },
                { //bottom-right
                    size: new OpenLayers.Size(22, 21),
                    anchor: new OpenLayers.Bounds(null, 0, 0, null),
                    position: new OpenLayers.Pixel(-638, -629)
                },
                { // stem
                    size: new OpenLayers.Size(81, 33),
                    anchor: new OpenLayers.Bounds(0, null, null, 0),
                    position: new OpenLayers.Pixel(-311, -674)
                }
            ]
        }
    },

    /**
     * APIProperty: minSize
     * {<OpenLayers.Size>}
     */
    minSize: new OpenLayers.Size(105, 10),

    /**
     * APIProperty: maxSize
     * {<OpenLayers.Size>}
     */
    maxSize: new OpenLayers.Size(600, 660),

    /**
     * Constructor: OpenLayers.Popup.FramedCloud
     *
     * Parameters:
     * id - {String}
     * lonlat - {<OpenLayers.LonLat>}
     * contentSize - {<OpenLayers.Size>}
     * contentHTML - {String}
     * anchor - {Object} Object to which we'll anchor the popup. Must expose
     *     a 'size' (<OpenLayers.Size>) and 'offset' (<OpenLayers.Pixel>)
     *     (Note that this is generally an <OpenLayers.Icon>).
     * closeBox - {Boolean}
     * closeBoxCallback - {Function} Function to be called on closeBox click.
     */
    initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
                        closeBoxCallback) {

        this.imageSrc = OpenLayers.Util.getImagesLocation() + 'cloud-popup-relative.png';
        OpenLayers.Popup.Framed.prototype.initialize.apply(this, arguments);
        this.contentDiv.className = this.contentDisplayClass;
    },

    /**
     * APIMethod: destroy
     */
    destroy: function() {
        OpenLayers.Popup.Framed.prototype.destroy.apply(this, arguments);
    },

    CLASS_NAME: "OpenLayers.Popup.FramedCloud"
});
<|endoftext|>


<commit_before>define([
	'goo/math/Vector2'
],
/** @lends */
function (
	Vector2
) {
	'use strict';

	/**
	 * @class Texture defines a texture object to be used to display an image on a piece of geometry. The image to be displayed is
	 *        defined by the Image class. All attributes required for texture mapping are contained within this class. This includes
	 *        mipmapping if desired, magnificationFilter options, apply options and correction options. Default values are as follows:
	 *        minificationFilter - NearestNeighborNoMipMaps, magnificationFilter - NearestNeighbor, wrap - EdgeClamp on S,T and R, apply - Modulate,
	 *        environment - None.
	 * @param {Image} image Image to use as base for texture
	 * @param {object} settings Texturing settings
	 * @param {string} [settings.wrapS='Repeat'] possible values:
	 *

	 *
'Repeat' = Repeat texture (ignore integer part of texture coords)
	 *
'MirroredRepeat' = Repeat with reversed direction on odd integer part of texture coords
	 *
'EdgeClamp' = Clamp texture coord range to 0..1 and use edge color
	 *

	 * @param {string} [settings.wrapT='Repeat'] possible values:
	 *

	 *
'Repeat' = Repeat texture (ignore integer part of texture coords)
	 *
'MirroredRepeat' = Repeat with reversed direction on odd integer part of texture coords
	 *
'EdgeClamp' = Clamp texture coord range to 0..1 and use edge color
	 *

	 * @param {string} [settings.magFilter='Bilinear'] possible values:
	 *

	 *
'NearestNeighbor' =
	 *
'Bilinear' =
	 *

	 * @param {string} [settings.minFilter='TriLinear'] possible values:
	 *

	 *
'NearestNeighborNoMipMaps' =
	 *
'NearestNeighborNearestMipMap' =
	 *
'NearestNeighborLinearMipMap' =
	 *
'BilinearNoMipMaps' =
	 *
'BilinearNearestMipMap' =
	 *
'Trilinear' =
	 *

	 * @param {number} [settings.anisotropy=1] Amount of anisotropic filtering (1=1x, 4=4x etc, max usually 4 or 16. Card max in renderer.capabilities.maxAnisotropy)
	 * @param {string} [settings.format='RGBA'] possible values:
	 *

	 *
'RGBA' =
	 *
'RGB' =
	 *
'Alpha' =
	 *
'Luminance' =
	 *
'LuminanceAlpha' =
	 *

	 * @param {string} [settings.type='UnsignedByte'] possible values:
	 *

	 *
'UnsignedByte' =
	 *
'UnsignedShort565' =
	 *
'UnsignedShort4444' =
	 *
'UnsignedShort5551' =
	 *
'Float' =
	 *

	 * @param {Array} [settings.offset=(0,0)] Texture offset
	 * @param {Array} [settings.repeat=(1,1)] Texture repeat/scale
	 * @param {boolean} [settings.generateMipmaps='true'] Automatically generate mipmaps
	 * @param {boolean} [settings.premultiplyAlpha='false'] Premultiply alpha
	 * @param {number} [settings.unpackAlignment=1] Unpack alignment setting
	 * @param {boolean} [settings.flipY='true'] Flip texture in y-axis
	 */
	function Texture(image, settings, width, height) {
		this.glTexture = null;

		settings = settings || {};

		this.wrapS = settings.wrapS || 'Repeat';
		this.wrapT = settings.wrapT || 'Repeat';

		this.magFilter = settings.magFilter || 'Bilinear';
		this.minFilter = settings.minFilter || 'Trilinear';

		this.anisotropy = settings.anisotropy !== undefined ? settings.anisotropy : 1;

		this.format = settings.format || 'RGBA';
		this.type = settings.type || 'UnsignedByte';
		this.variant = '2D'; // CUBE

		this.offset = new Vector2(settings.offset || [0, 0]);
		this.repeat = new Vector2(settings.repeat || [1, 1]);
		this.lodBias = 0.0;

		this.generateMipmaps = settings.generateMipmaps !== undefined ? settings.generateMipmaps : true;
		this.premultiplyAlpha = settings.premultiplyAlpha !== undefined ? settings.premultiplyAlpha : false;
		this.unpackAlignment = settings.unpackAlignment !== undefined ? settings.unpackAlignment : 1;
		this.flipY = settings.flipY !== undefined ? settings.flipY : true;

		this.hasBorder = false;

		this.needsUpdate = false;
		this.updateCallback = null;
		this.readyCallback = null;

		if (image) {
			this.setImage(image, width, height, settings);
		}
	}

	Texture.prototype.checkDataReady = function () {
		return this.image && (this.image.dataReady || this.image instanceof HTMLImageElement) || this.readyCallback !== null && this.readyCallback();
	};

	Texture.prototype.checkNeedsUpdate = function () {
		return this.needsUpdate || this.updateCallback !== null && this.updateCallback();
	};

	/**
	 * Marks the texture as needing to be updated by the engine.
	 */
	Texture.prototype.setNeedsUpdate = function () {
		this.needsUpdate = true;
	};

	/**
	 * Sets an image on the texture object.
	 *
	 * @param {Image} image The image to set. Can be an Image, TypedArray or an array of Images (for cubemaps)
	 * @param {Number} [width]
	 * @param {Number} [height]
	 */
	Texture.prototype.setImage = function (image, width, height, settings) {
		this.image = image;

		var data = image instanceof Array ? image[0] : image;
		if (data instanceof Uint8Array || data instanceof Uint8ClampedArray || data instanceof Uint16Array || data instanceof Float32Array) {
			width = width || image.width;
			height = height || image.height;
			if (width !== undefined && height !== undefined) {
				this.image = {
					data: image
				};
				this.image.width = width;
				this.image.height = height;
				this.image.isData = true;
				this.image.dataReady = true;
				if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) {
					this.type = 'UnsignedByte';
				} else if (data instanceof Uint16Array) {
					this.type = 'UnsignedShort565';
					this.format = settings.format || 'RGB';
				} else if (data instanceof Float32Array) {
					this.type = 'Float';
					this.format = settings.format || 'RGBA';
				}
			} else {
				throw 'Data textures need width and height';
			}
		} else if (data instanceof HTMLCanvasElement) {
			// REVIEW This is done in the next else too, perhaps move out of this if? Talk with Rikard about it.
			if (image instanceof Array) {
				this.image = {
					data: image
				};
			}
			this.image.dataReady = true;
		} else {
			if (image instanceof Array) {
				this.image = {
					data: image
				};
			}
		}
		this.setNeedsUpdate();
	};

	/**
	 * Releases the allocated texture
	 * @param {WebGLRenderingContext} context
	 */
	Texture.prototype.destroy = function (context) {
		context.deleteTexture(this.glTexture);
	};

	Texture.CUBE_FACES = ['PositiveX', 'NegativeX', 'PositiveY', 'NegativeY', 'PositiveZ', 'NegativeZ'];

	return Texture;
});<commit_msg>post review on https://trello.com/c/aUwULEyg/1289-minor-adding-a-svg-as-skysphere-triggers-unknown-texture-type-error<commit_after>define([
	'goo/math/Vector2'
],
/** @lends */
function (
	Vector2
) {
	'use strict';

	/**
	 * @class Texture defines a texture object to be used to display an image on a piece of geometry. The image to be displayed is
	 *        defined by the Image class. All attributes required for texture mapping are contained within this class. This includes
	 *        mipmapping if desired, magnificationFilter options, apply options and correction options. Default values are as follows:
	 *        minificationFilter - NearestNeighborNoMipMaps, magnificationFilter - NearestNeighbor, wrap - EdgeClamp on S,T and R, apply - Modulate,
	 *        environment - None.
	 * @param {Image} image Image to use as base for texture
	 * @param {object} settings Texturing settings
	 * @param {string} [settings.wrapS='Repeat'] possible values:
	 *

	 *
'Repeat' = Repeat texture (ignore integer part of texture coords)
	 *
'MirroredRepeat' = Repeat with reversed direction on odd integer part of texture coords
	 *
'EdgeClamp' = Clamp texture coord range to 0..1 and use edge color
	 *

	 * @param {string} [settings.wrapT='Repeat'] possible values:
	 *

	 *
'Repeat' = Repeat texture (ignore integer part of texture coords)
	 *
'MirroredRepeat' = Repeat with reversed direction on odd integer part of texture coords
	 *
'EdgeClamp' = Clamp texture coord range to 0..1 and use edge color
	 *

	 * @param {string} [settings.magFilter='Bilinear'] possible values:
	 *

	 *
'NearestNeighbor' =
	 *
'Bilinear' =
	 *

	 * @param {string} [settings.minFilter='TriLinear'] possible values:
	 *

	 *
'NearestNeighborNoMipMaps' =
	 *
'NearestNeighborNearestMipMap' =
	 *
'NearestNeighborLinearMipMap' =
	 *
'BilinearNoMipMaps' =
	 *
'BilinearNearestMipMap' =
	 *
'Trilinear' =
	 *

	 * @param {number} [settings.anisotropy=1] Amount of anisotropic filtering (1=1x, 4=4x etc, max usually 4 or 16. Card max in renderer.capabilities.maxAnisotropy)
	 * @param {string} [settings.format='RGBA'] possible values:
	 *

	 *
'RGBA' =
	 *
'RGB' =
	 *
'Alpha' =
	 *
'Luminance' =
	 *
'LuminanceAlpha' =
	 *

	 * @param {string} [settings.type='UnsignedByte'] possible values:
	 *

	 *
'UnsignedByte' =
	 *
'UnsignedShort565' =
	 *
'UnsignedShort4444' =
	 *
'UnsignedShort5551' =
	 *
'Float' =
	 *

	 * @param {Array} [settings.offset=(0,0)] Texture offset
	 * @param {Array} [settings.repeat=(1,1)] Texture repeat/scale
	 * @param {boolean} [settings.generateMipmaps='true'] Automatically generate mipmaps
	 * @param {boolean} [settings.premultiplyAlpha='false'] Premultiply alpha
	 * @param {number} [settings.unpackAlignment=1] Unpack alignment setting
	 * @param {boolean} [settings.flipY='true'] Flip texture in y-axis
	 */
	function Texture(image, settings, width, height) {
		this.glTexture = null;

		settings = settings || {};

		this.wrapS = settings.wrapS || 'Repeat';
		this.wrapT = settings.wrapT || 'Repeat';

		this.magFilter = settings.magFilter || 'Bilinear';
		this.minFilter = settings.minFilter || 'Trilinear';

		this.anisotropy = settings.anisotropy !== undefined ? settings.anisotropy : 1;

		this.format = settings.format || 'RGBA';
		this.type = settings.type || 'UnsignedByte';
		this.variant = '2D'; // CUBE

		this.offset = new Vector2(settings.offset || [0, 0]);
		this.repeat = new Vector2(settings.repeat || [1, 1]);
		this.lodBias = 0.0;

		this.generateMipmaps = settings.generateMipmaps !== undefined ? settings.generateMipmaps : true;
		this.premultiplyAlpha = settings.premultiplyAlpha !== undefined ? settings.premultiplyAlpha : false;
		this.unpackAlignment = settings.unpackAlignment !== undefined ? settings.unpackAlignment : 1;
		this.flipY = settings.flipY !== undefined ? settings.flipY : true;

		this.hasBorder = false;

		this.needsUpdate = false;
		this.updateCallback = null;
		this.readyCallback = null;

		if (image) {
			this.setImage(image, width, height, settings);
		}
	}

	Texture.prototype.checkDataReady = function () {
		return this.image && (this.image.dataReady || this.image instanceof HTMLImageElement) || this.readyCallback !== null && this.readyCallback();
	};

	Texture.prototype.checkNeedsUpdate = function () {
		return this.needsUpdate || this.updateCallback !== null && this.updateCallback();
	};

	/**
	 * Marks the texture as needing to be updated by the engine.
	 */
	Texture.prototype.setNeedsUpdate = function () {
		this.needsUpdate = true;
	};

	/**
	 * Sets an image on the texture object.
	 *
	 * @param {Image} image The image to set. Can be an Image, TypedArray or an array of Images (for cubemaps)
	 * @param {Number} [width]
	 * @param {Number} [height]
	 */
	Texture.prototype.setImage = function (image, width, height, settings) {
		this.image = image;

		var data = image instanceof Array ? image[0] : image;
		if (data instanceof Uint8Array || data instanceof Uint8ClampedArray || data instanceof Uint16Array || data instanceof Float32Array) {
			width = width || image.width;
			height = height || image.height;
			if (width !== undefined && height !== undefined) {
				this.image = {
					data: image
				};
				this.image.width = width;
				this.image.height = height;
				this.image.isData = true;
				this.image.dataReady = true;
				if (data instanceof Uint8Array || data instanceof Uint8ClampedArray) {
					this.type = 'UnsignedByte';
				} else if (data instanceof Uint16Array) {
					this.type = 'UnsignedShort565';
					this.format = settings.format || 'RGB';
				} else if (data instanceof Float32Array) {
					this.type = 'Float';
					this.format = settings.format || 'RGBA';
				}
			} else {
				throw 'Data textures need width and height';
			}
		} else {
			if (image instanceof Array) {
				this.image = {
					data: image
				};
			}
			if (data instanceof HTMLCanvasElement) {
				this.image.dataReady = true;
			}
		}
		this.setNeedsUpdate();
	};

	/**
	 * Releases the allocated texture
	 * @param {WebGLRenderingContext} context
	 */
	Texture.prototype.destroy = function (context) {
		context.deleteTexture(this.glTexture);
	};

	Texture.CUBE_FACES = ['PositiveX', 'NegativeX', 'PositiveY', 'NegativeY', 'PositiveZ', 'NegativeZ'];

	return Texture;
});<|endoftext|>


<commit_before>/* eslint-disable no-console */
/* global openInBrowser, BigNumber */
(function () {
    'use strict';

    const locationHref = location.href;
    const tsUtils = require('ts-utils');
    const i18next = require('i18next');
    const { propEq, where, gte, lte, equals, path } = require('ramda');

    const i18nextReady = new Promise(resolve => {
        const handler = data => {
            resolve(data);
            i18next.off('initialized', handler);
        };
        i18next.on('initialized', handler);
    });

    const PROGRESS_MAP = {
        RUN_SCRIPT: 10,
        APP_RUN: 15,
        LOCALIZE_READY: 25,
        IMAGES_LOADED: 50
    };

    const allProgress = Object.values(PROGRESS_MAP)
        .reduce((result, item) => result + item, 0);
    if (allProgress !== 100) {
        throw new Error('Configure loader progress!');
    }

    const LOADER = {
        _current: 0,
        _root: document.querySelector('.app-loader'),
        _element: document.querySelector('.app-loader .progress'),
        addProgress(delta) {
            this._current += delta;
            this._current = Math.min(this._current, 100);
            this._element.style.width = `${this._current}%`;
            WavesApp.progress = this._current;
        },
        stop() {
            return new Promise(resolve => {
                const loader = $(this._root);
                loader.fadeOut(1000, () => {
                    loader.remove();
                    resolve();
                });
            });
        }
    };

    LOADER.addProgress(PROGRESS_MAP.RUN_SCRIPT);
    WavesApp.state = 'initApp';
    /**
     * @param {$rootScope.Scope} $rootScope
     * @param {User} user
     * @param {app.utils} utils
     * @param $state
     * @param {State} state
     * @param {ModalManager} modalManager
     * @param {Storage} storage
     * @param {INotification} notification
     * @param {app.utils.decorators} decorators
     * @param {Waves} waves
     * @param {ModalRouter} ModalRouter
     * @param {ConfigService} configService
     * @param {INotification} userNotification
     * @return {AppRun}
     */
    const run = function ($rootScope, utils, user, $state, state, modalManager, storage,
                          notification, decorators, waves, ModalRouter, configService, userNotification) {

        const phone = WavesApp.device.phone();
        const tablet = WavesApp.device.tablet();

        const isPhone = !!phone;
        const isTablet = !!tablet;
        const isDesktop = !(isPhone || isTablet);

        $rootScope.isDesktop = isDesktop;
        $rootScope.isNotDesktop = !isDesktop;
        $rootScope.isPhone = isPhone;
        $rootScope.isNotPhone = !isPhone;
        $rootScope.isTablet = isTablet;

        if (isPhone) {
            document.body.classList.add('phone');
        } else if (isTablet) {
            document.body.classList.add('tablet');
        } else {
            document.body.classList.add('desktop');
        }

        class AppRun {

            constructor() {
                const identityImg = require('identity-img');

                LOADER.addProgress(PROGRESS_MAP.APP_RUN);

                /**
                 * List of css class on body (from current state)
                 * @type {Array<string>}
                 */
                this.activeClasses = [];
                /**
                 * @type {ModalRouter}
                 * @private
                 */
                this._modalRouter = new ModalRouter();

                /**
                 * Configure library generation avatar by address
                 */
                identityImg.config({ rows: 8, cells: 8 });

                this._setHandlers();
                this._stopLoader();
                this._initializeLogin();
                this._initializeOutLinks();

                Promise.all([
                    user.onLogin(),
                    i18nextReady
                ]).then(() => {
                    this._updateUserNotifications();
                    setInterval(() => this._updateUserNotifications(), 10000);
                });

                if (WavesApp.isDesktop()) {
                    window.listenMainProcessEvent((type, url) => {
                        const parts = utils.parseElectronUrl(url);
                        const path = parts.path.replace(/\/$/, '') || parts.path;
                        if (path) {
                            const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }).some(item => {
                                const url = item.get('url') || item.id;
                                return path === url;
                            });
                            if (noLogin) {
                                location.hash = `#!${path}${parts.search}`;
                            } else {
                                user.onLogin().then(() => {
                                    setTimeout(() => {
                                        location.hash = `#!${path}${parts.search}`;
                                    }, 1000);
                                });
                            }
                        }
                    });
                }

                $rootScope.WavesApp = WavesApp;
            }

            _initTryDesktop() {
                if (!isDesktop || WavesApp.isDesktop()) {
                    return Promise.resolve(true);
                }

                const url = new URL(locationHref);
                const href = `waves://${url.pathname}${url.search}${url.hash}`.replace('///', '//');

                return storage.load('openClientMode').then(clientMode => {
                    switch (clientMode) {
                        case 'desktop':
                            window.open(href);
                            return this._runDesktop();
                        case 'web':
                            return Promise.resolve(true);
                        default:
                            return modalManager.showTryDesktopModal()
                                .then(() => this._runDesktop())
                                .catch(() => true);
                    }
                });
            }

            _runDesktop() {
                this._canOpenDesktopPage = true;
                $state.go('desktop');

                return false;
            }

            /**
             * @private
             */
            _setHandlers() {
                $rootScope.$on('$stateChangeSuccess', this._onChangeStateSuccess.bind(this));
            }

            /**
             * Initialize handler for out links for electron
             * @private
             */
            _initializeOutLinks() {
                if (WavesApp.isDesktop()) {
                    $(document).on('click', '[target="_blank"]', (e) => {
                        const $link = $(e.currentTarget);
                        e.preventDefault();

                        openInBrowser($link.attr('href'));
                    });
                }
            }

            /**
             * @private
             */
            _updateUserNotifications() {
                const notifications = configService.get('NOTIFICATIONS') || [];
                const time = ds.utils.normalizeTime(Date.now());

                const closed = user.getSetting('closedNotification')
                    .filter(id => notifications.some(propEq('id', id)));
                user.setSetting('closedNotification', closed);

                const notificationsWithDate = notifications
                    .map(item => ({
                        ...item,
                        start_date: new Date(item.start_date),
                        end_date: new Date(item.end_date)
                    }));

                notificationsWithDate
                    .filter(where({
                        start_date: gte(time),
                        end_date: lte(time),
                        id: id => !(userNotification.has(id) || closed.includes(id))
                    }))
                    .forEach(item => {
                        const method = ['warn', 'success', 'error', 'info'].find(equals(item.type)) || 'warn';
                        const en = path(['text', 'en'], item);
                        const lang = path(['text', i18next.language], item) || en;

                        userNotification[method]({
                            ...item,
                            body: {
                                literal: lang
                            }
                        }).then(() => {
                            user.setSetting('closedNotification', [
                                item.id,
                                ...user.getSetting('closedNotification')
                            ]);
                        });
                    });

                notificationsWithDate.filter(where({ end_date: lte(time) }))
                    .forEach(item => userNotification.remove(item.id));
            }

            /**
             * @private
             */
            _listenChangeLanguage() {
                i18next.on('languageChanged', this._changeLangHandler);
            }

            /**
             * @private
             */
            _stopListenChangeLanguage() {
                i18next.off('languageChanged', this._changeLangHandler);
            }

            /**
             * @private
             */
            _changeLangHandler() {
                localStorage.setItem('lng', i18next.language);
            }

            /**
             * @private
             */
            _initializeLogin() {

                let needShowTutorial = false;

                this._listenChangeLanguage();

                const START_STATES = WavesApp.stateTree.where({ noLogin: true })
                    .map((item) => WavesApp.stateTree.getPath(item.id).join('.'));

                let waiting = false;

                const stop = $rootScope.$on('$stateChangeStart', (event, toState, params) => {

                    let tryDesktop;

                    if (START_STATES.indexOf(toState.name) === -1) {
                        event.preventDefault();
                    }

                    if (toState.name === 'desktop' && !this._canOpenDesktopPage) {
                        event.preventDefault();
                        $state.go(START_STATES[0]);
                    }

                    if (waiting) {
                        return null;
                    }

                    if (needShowTutorial && toState.name !== 'dex-demo') {
                        modalManager.showTutorialModals();
                        needShowTutorial = false;
                    }

                    if (toState.name === 'main.dex-demo') {
                        tryDesktop = Promise.resolve();
                    } else {
                        tryDesktop = this._initTryDesktop();
                    }

                    const promise = Promise.all([
                        storage.onReady(),
                        tryDesktop
                    ]).then(([oldVersion, canOpenTutorial]) => {
                        needShowTutorial = canOpenTutorial && !oldVersion;
                    });

                    promise.then(() => {
                        if (needShowTutorial && toState.name !== 'dex-demo') {
                            modalManager.showTutorialModals();
                            needShowTutorial = false;
                        }
                    });

                    waiting = true;

                    tryDesktop
                        .then((canChangeState) => this._login(toState, canChangeState))
                        .then(() => {
                            stop();

                            this._stopListenChangeLanguage();
                            if (START_STATES.indexOf(toState.name) === -1) {
                                $state.go(toState.name, params);
                            } else {
                                $state.go(user.getActiveState('wallet'));
                            }

                            i18next.changeLanguage(user.getSetting('lng'));

                            this._initializeTermsAccepted()
                                .then(() => {
                                    this._initializeBackupWarning();
                                })
                                .then(() => {
                                    this._modalRouter.initialize();
                                });

                            $rootScope.$on('$stateChangeStart', (event, current) => {
                                if (START_STATES.indexOf(current.name) !== -1) {
                                    event.preventDefault();
                                } else {
                                    state.signals.changeRouterStateStart.dispatch(event);
                                }
                            });
                        });
                });
            }

            /**
             * @return Promise
             * @private
             */
            _initializeTermsAccepted() {
                if (!user.getSetting('termsAccepted')) {
                    return modalManager.showTermsAccept(user).then(() => {
                        if (user.getSetting('shareAnalytics')) {
                            analytics.activate();
                        }
                    })
                        .catch(() => false);
                } else if (user.getSetting('shareAnalytics')) {
                    analytics.activate();
                }
                return Promise.resolve();
            }

            /**
             * @param {object} [scope]
             * @param {boolean} scope.closeByModal
             * @private
             */
            @decorators.scope({ closeByModal: false })
            _initializeBackupWarning(scope) {
                if (!user.getSetting('hasBackup')) {

                    const id = tsUtils.uniqueId('n');

                    const changeModalsHandler = (modal) => {

                        scope.closeByModal = true;
                        notification.remove(id);
                        scope.closeByModal = false;

                        modal.catch(() => null)
                            .then(() => {
                                if (!user.getSetting('hasBackup')) {
                                    this._initializeBackupWarning();
                                }
                            });
                    };

                    modalManager.openModal.once(changeModalsHandler);

                    notification.error({
                        id,
                        ns: 'app.utils',
                        title: {
                            literal: 'notification.backup.title'
                        },
                        body: {
                            literal: 'notification.backup.body'
                        },
                        action: {
                            literal: 'notification.backup.action',
                            callback: () => {
                                modalManager.showSeedBackupModal();
                            }
                        },
                        onClose: () => {
                            if (scope.closeByModal || user.getSetting('hasBackup')) {
                                return null;
                            }

                            modalManager.openModal.off(changeModalsHandler);

                            const stop = $rootScope.$on('$stateChangeSuccess', () => {
                                stop();
                                this._initializeBackupWarning();
                            });
                        }
                    }, -1);
                }
            }

            /**
             * @param {{name: string}} currentState
             * @param {boolean} canChangeState
             * @return {Promise}
             * @private
             */
            _login(currentState, canChangeState) {
                // const sessions = sessionBridge.getSessionsData();

                const states = WavesApp.stateTree.where({ noLogin: true })
                    .map((item) => {
                        return WavesApp.stateTree.getPath(item.id)
                            .join('.');
                    });
                if (canChangeState && states.indexOf(currentState.name) === -1) {
                    // if (sessions.length) {
                    //     $state.go('sessions');
                    // } else {
                    $state.go(states[0]);
                    // }
                }

                return user.onLogin();
            }

            /**
             * @param {Event} event
             * @param {object} toState
             * @param some
             * @param fromState
             * @param {string} toState.name
             * @private
             */
            _onChangeStateSuccess(event, toState, some, fromState) {
                if (fromState.name) {
                    analytics.pushPageView(
                        `${AppRun._getUrlFromState(toState)}.${WavesApp.type}`,
                        `${AppRun._getUrlFromState(fromState)}.${WavesApp.type}`
                    );
                }
                this.activeClasses.forEach((className) => {
                    document.body.classList.remove(className);
                });
                this.activeClasses = [];
                toState.name.split('.')
                    .filter(Boolean)
                    .forEach((className) => {
                        const name = className.replace(/_/g, '-');
                        document.body.classList.add(name);
                        this.activeClasses.push(name);
                    });
                user.applyState(toState);
                state.signals.changeRouterStateSuccess.dispatch(toState);
            }

            /**
             * @private
             */
            _stopLoader() {
                Promise.all([
                    this._getLocalizeReadyPromise(),
                    this._getImagesReadyPromise()
                ])
                    .then(() => {
                        LOADER.stop();
                        WavesApp.state = 'appRun';
                    })
                    .catch((e) => {
                        console.error(e);
                        WavesApp.state = 'loadingError';
                    });
            }

            /**
             * @return {Promise}
             * @private
             */
            _getLocalizeReadyPromise() {
                return new Promise((resolve) => {
                    i18next.on('initialized', () => {
                        LOADER.addProgress(PROGRESS_MAP.LOCALIZE_READY);
                        resolve();
                    });
                });
            }

            /**
             * @private
             */
            _getImagesReadyPromise() {
                return $.ajax({ url: `/img/images-list.json?v=${WavesApp.version}`, dataType: 'json' })
                    .then((list) => {
                        return Promise.all(list.map(AppRun.getLoadImagePromise(list.length)));
                    });
            }

            static getLoadImagePromise(length) {
                return function (path) {
                    return new Promise(resolve => {
                        const img = new Image();
                        const apply = () => {
                            LOADER.addProgress(PROGRESS_MAP.IMAGES_LOADED / length);
                            resolve();
                        };

                        img.onload = apply;
                        img.onerror = () => {
                            console.warn(`Can't load image! "${path}"`);
                            apply();
                        };
                        img.src = path;
                    });
                };
            }

            static _getUrlFromState(state) {
                return (
                    WavesApp
                        .stateTree
                        .getPath(state.name.split('.').slice(-1)[0])
                        .filter((id) => !WavesApp.stateTree.find(id).get('abstract'))
                        .map((id) => WavesApp.stateTree.find(id).get('url') || id)
                        .reduce((url, id) => `${url}/${id}`, '')
                );
            }

        }

        return new AppRun();
    };

    run.$inject = [
        '$rootScope',
        'utils',
        'user',
        '$state',
        'state',
        'modalManager',
        'storage',
        'notification',
        'decorators',
        'waves',
        'ModalRouter',
        'configService',
        'userNotification',
        'whatsNew'
    ];

    angular.module('app')
        .run(run);
})();

/**
 * @property {boolean} $rootScope.Scope#isDesktop
 * @property {boolean} $rootScope.Scope#isNotDesktop
 * @property {boolean} $rootScope.Scope#isPhone
 * @property {boolean} $rootScope.Scope#isNotPhone
 * @property {boolean} $rootScope.Scope#isTablet
 */
<commit_msg>CLIENT-1576: fix filters<commit_after>/* eslint-disable no-console */
/* global openInBrowser, BigNumber */
(function () {
    'use strict';

    const locationHref = location.href;
    const tsUtils = require('ts-utils');
    const i18next = require('i18next');
    const { propEq, where, gte, lte, equals, path, __ } = require('ramda');

    const i18nextReady = new Promise(resolve => {
        const handler = data => {
            resolve(data);
            i18next.off('initialized', handler);
        };
        i18next.on('initialized', handler);
    });

    const PROGRESS_MAP = {
        RUN_SCRIPT: 10,
        APP_RUN: 15,
        LOCALIZE_READY: 25,
        IMAGES_LOADED: 50
    };

    const allProgress = Object.values(PROGRESS_MAP)
        .reduce((result, item) => result + item, 0);
    if (allProgress !== 100) {
        throw new Error('Configure loader progress!');
    }

    const LOADER = {
        _current: 0,
        _root: document.querySelector('.app-loader'),
        _element: document.querySelector('.app-loader .progress'),
        addProgress(delta) {
            this._current += delta;
            this._current = Math.min(this._current, 100);
            this._element.style.width = `${this._current}%`;
            WavesApp.progress = this._current;
        },
        stop() {
            return new Promise(resolve => {
                const loader = $(this._root);
                loader.fadeOut(1000, () => {
                    loader.remove();
                    resolve();
                });
            });
        }
    };

    LOADER.addProgress(PROGRESS_MAP.RUN_SCRIPT);
    WavesApp.state = 'initApp';
    /**
     * @param {$rootScope.Scope} $rootScope
     * @param {User} user
     * @param {app.utils} utils
     * @param $state
     * @param {State} state
     * @param {ModalManager} modalManager
     * @param {Storage} storage
     * @param {INotification} notification
     * @param {app.utils.decorators} decorators
     * @param {Waves} waves
     * @param {ModalRouter} ModalRouter
     * @param {ConfigService} configService
     * @param {INotification} userNotification
     * @return {AppRun}
     */
    const run = function ($rootScope, utils, user, $state, state, modalManager, storage,
                          notification, decorators, waves, ModalRouter, configService, userNotification) {

        const phone = WavesApp.device.phone();
        const tablet = WavesApp.device.tablet();

        const isPhone = !!phone;
        const isTablet = !!tablet;
        const isDesktop = !(isPhone || isTablet);

        $rootScope.isDesktop = isDesktop;
        $rootScope.isNotDesktop = !isDesktop;
        $rootScope.isPhone = isPhone;
        $rootScope.isNotPhone = !isPhone;
        $rootScope.isTablet = isTablet;

        if (isPhone) {
            document.body.classList.add('phone');
        } else if (isTablet) {
            document.body.classList.add('tablet');
        } else {
            document.body.classList.add('desktop');
        }

        class AppRun {

            constructor() {
                const identityImg = require('identity-img');

                LOADER.addProgress(PROGRESS_MAP.APP_RUN);

                /**
                 * List of css class on body (from current state)
                 * @type {Array<string>}
                 */
                this.activeClasses = [];
                /**
                 * @type {ModalRouter}
                 * @private
                 */
                this._modalRouter = new ModalRouter();

                /**
                 * Configure library generation avatar by address
                 */
                identityImg.config({ rows: 8, cells: 8 });

                this._setHandlers();
                this._stopLoader();
                this._initializeLogin();
                this._initializeOutLinks();

                Promise.all([
                    user.onLogin(),
                    i18nextReady
                ]).then(() => {
                    this._updateUserNotifications();
                    setInterval(() => this._updateUserNotifications(), 10000);
                });

                if (WavesApp.isDesktop()) {
                    window.listenMainProcessEvent((type, url) => {
                        const parts = utils.parseElectronUrl(url);
                        const path = parts.path.replace(/\/$/, '') || parts.path;
                        if (path) {
                            const noLogin = path === '/' || WavesApp.stateTree.where({ noLogin: true }).some(item => {
                                const url = item.get('url') || item.id;
                                return path === url;
                            });
                            if (noLogin) {
                                location.hash = `#!${path}${parts.search}`;
                            } else {
                                user.onLogin().then(() => {
                                    setTimeout(() => {
                                        location.hash = `#!${path}${parts.search}`;
                                    }, 1000);
                                });
                            }
                        }
                    });
                }

                $rootScope.WavesApp = WavesApp;
            }

            _initTryDesktop() {
                if (!isDesktop || WavesApp.isDesktop()) {
                    return Promise.resolve(true);
                }

                const url = new URL(locationHref);
                const href = `waves://${url.pathname}${url.search}${url.hash}`.replace('///', '//');

                return storage.load('openClientMode').then(clientMode => {
                    switch (clientMode) {
                        case 'desktop':
                            window.open(href);
                            return this._runDesktop();
                        case 'web':
                            return Promise.resolve(true);
                        default:
                            return modalManager.showTryDesktopModal()
                                .then(() => this._runDesktop())
                                .catch(() => true);
                    }
                });
            }

            _runDesktop() {
                this._canOpenDesktopPage = true;
                $state.go('desktop');

                return false;
            }

            /**
             * @private
             */
            _setHandlers() {
                $rootScope.$on('$stateChangeSuccess', this._onChangeStateSuccess.bind(this));
            }

            /**
             * Initialize handler for out links for electron
             * @private
             */
            _initializeOutLinks() {
                if (WavesApp.isDesktop()) {
                    $(document).on('click', '[target="_blank"]', (e) => {
                        const $link = $(e.currentTarget);
                        e.preventDefault();

                        openInBrowser($link.attr('href'));
                    });
                }
            }

            /**
             * @private
             */
            _updateUserNotifications() {
                const notifications = configService.get('NOTIFICATIONS') || [];
                const time = ds.utils.normalizeTime(Date.now());

                const closed = user.getSetting('closedNotification')
                    .filter(id => notifications.some(propEq('id', id)));
                user.setSetting('closedNotification', closed);

                const notificationsWithDate = notifications
                    .map(item => ({
                        ...item,
                        start_date: new Date(item.start_date),
                        end_date: new Date(item.end_date)
                    }));

                notificationsWithDate
                    .filter(where({
                        start_date: gte(__, time),
                        end_date: lte(__, time),
                        id: id => !(userNotification.has(id) || closed.includes(id))
                    }))
                    .forEach(item => {
                        const method = ['warn', 'success', 'error', 'info'].find(equals(item.type)) || 'warn';
                        const en = path(['text', 'en'], item);
                        const lang = path(['text', i18next.language], item) || en;

                        userNotification[method]({
                            ...item,
                            body: {
                                literal: lang
                            }
                        }).then(() => {
                            user.setSetting('closedNotification', [
                                item.id,
                                ...user.getSetting('closedNotification')
                            ]);
                        });
                    });

                notificationsWithDate.filter(where({ end_date: lte(__, time) }))
                    .forEach(item => userNotification.remove(item.id));
            }

            /**
             * @private
             */
            _listenChangeLanguage() {
                i18next.on('languageChanged', this._changeLangHandler);
            }

            /**
             * @private
             */
            _stopListenChangeLanguage() {
                i18next.off('languageChanged', this._changeLangHandler);
            }

            /**
             * @private
             */
            _changeLangHandler() {
                localStorage.setItem('lng', i18next.language);
            }

            /**
             * @private
             */
            _initializeLogin() {

                let needShowTutorial = false;

                this._listenChangeLanguage();

                const START_STATES = WavesApp.stateTree.where({ noLogin: true })
                    .map((item) => WavesApp.stateTree.getPath(item.id).join('.'));

                let waiting = false;

                const stop = $rootScope.$on('$stateChangeStart', (event, toState, params) => {

                    let tryDesktop;

                    if (START_STATES.indexOf(toState.name) === -1) {
                        event.preventDefault();
                    }

                    if (toState.name === 'desktop' && !this._canOpenDesktopPage) {
                        event.preventDefault();
                        $state.go(START_STATES[0]);
                    }

                    if (waiting) {
                        return null;
                    }

                    if (needShowTutorial && toState.name !== 'dex-demo') {
                        modalManager.showTutorialModals();
                        needShowTutorial = false;
                    }

                    if (toState.name === 'main.dex-demo') {
                        tryDesktop = Promise.resolve();
                    } else {
                        tryDesktop = this._initTryDesktop();
                    }

                    const promise = Promise.all([
                        storage.onReady(),
                        tryDesktop
                    ]).then(([oldVersion, canOpenTutorial]) => {
                        needShowTutorial = canOpenTutorial && !oldVersion;
                    });

                    promise.then(() => {
                        if (needShowTutorial && toState.name !== 'dex-demo') {
                            modalManager.showTutorialModals();
                            needShowTutorial = false;
                        }
                    });

                    waiting = true;

                    tryDesktop
                        .then((canChangeState) => this._login(toState, canChangeState))
                        .then(() => {
                            stop();

                            this._stopListenChangeLanguage();
                            if (START_STATES.indexOf(toState.name) === -1) {
                                $state.go(toState.name, params);
                            } else {
                                $state.go(user.getActiveState('wallet'));
                            }

                            i18next.changeLanguage(user.getSetting('lng'));

                            this._initializeTermsAccepted()
                                .then(() => {
                                    this._initializeBackupWarning();
                                })
                                .then(() => {
                                    this._modalRouter.initialize();
                                });

                            $rootScope.$on('$stateChangeStart', (event, current) => {
                                if (START_STATES.indexOf(current.name) !== -1) {
                                    event.preventDefault();
                                } else {
                                    state.signals.changeRouterStateStart.dispatch(event);
                                }
                            });
                        });
                });
            }

            /**
             * @return Promise
             * @private
             */
            _initializeTermsAccepted() {
                if (!user.getSetting('termsAccepted')) {
                    return modalManager.showTermsAccept(user).then(() => {
                        if (user.getSetting('shareAnalytics')) {
                            analytics.activate();
                        }
                    })
                        .catch(() => false);
                } else if (user.getSetting('shareAnalytics')) {
                    analytics.activate();
                }
                return Promise.resolve();
            }

            /**
             * @param {object} [scope]
             * @param {boolean} scope.closeByModal
             * @private
             */
            @decorators.scope({ closeByModal: false })
            _initializeBackupWarning(scope) {
                if (!user.getSetting('hasBackup')) {

                    const id = tsUtils.uniqueId('n');

                    const changeModalsHandler = (modal) => {

                        scope.closeByModal = true;
                        notification.remove(id);
                        scope.closeByModal = false;

                        modal.catch(() => null)
                            .then(() => {
                                if (!user.getSetting('hasBackup')) {
                                    this._initializeBackupWarning();
                                }
                            });
                    };

                    modalManager.openModal.once(changeModalsHandler);

                    notification.error({
                        id,
                        ns: 'app.utils',
                        title: {
                            literal: 'notification.backup.title'
                        },
                        body: {
                            literal: 'notification.backup.body'
                        },
                        action: {
                            literal: 'notification.backup.action',
                            callback: () => {
                                modalManager.showSeedBackupModal();
                            }
                        },
                        onClose: () => {
                            if (scope.closeByModal || user.getSetting('hasBackup')) {
                                return null;
                            }

                            modalManager.openModal.off(changeModalsHandler);

                            const stop = $rootScope.$on('$stateChangeSuccess', () => {
                                stop();
                                this._initializeBackupWarning();
                            });
                        }
                    }, -1);
                }
            }

            /**
             * @param {{name: string}} currentState
             * @param {boolean} canChangeState
             * @return {Promise}
             * @private
             */
            _login(currentState, canChangeState) {
                // const sessions = sessionBridge.getSessionsData();

                const states = WavesApp.stateTree.where({ noLogin: true })
                    .map((item) => {
                        return WavesApp.stateTree.getPath(item.id)
                            .join('.');
                    });
                if (canChangeState && states.indexOf(currentState.name) === -1) {
                    // if (sessions.length) {
                    //     $state.go('sessions');
                    // } else {
                    $state.go(states[0]);
                    // }
                }

                return user.onLogin();
            }

            /**
             * @param {Event} event
             * @param {object} toState
             * @param some
             * @param fromState
             * @param {string} toState.name
             * @private
             */
            _onChangeStateSuccess(event, toState, some, fromState) {
                if (fromState.name) {
                    analytics.pushPageView(
                        `${AppRun._getUrlFromState(toState)}.${WavesApp.type}`,
                        `${AppRun._getUrlFromState(fromState)}.${WavesApp.type}`
                    );
                }
                this.activeClasses.forEach((className) => {
                    document.body.classList.remove(className);
                });
                this.activeClasses = [];
                toState.name.split('.')
                    .filter(Boolean)
                    .forEach((className) => {
                        const name = className.replace(/_/g, '-');
                        document.body.classList.add(name);
                        this.activeClasses.push(name);
                    });
                user.applyState(toState);
                state.signals.changeRouterStateSuccess.dispatch(toState);
            }

            /**
             * @private
             */
            _stopLoader() {
                Promise.all([
                    this._getLocalizeReadyPromise(),
                    this._getImagesReadyPromise()
                ])
                    .then(() => {
                        LOADER.stop();
                        WavesApp.state = 'appRun';
                    })
                    .catch((e) => {
                        console.error(e);
                        WavesApp.state = 'loadingError';
                    });
            }

            /**
             * @return {Promise}
             * @private
             */
            _getLocalizeReadyPromise() {
                return new Promise((resolve) => {
                    i18next.on('initialized', () => {
                        LOADER.addProgress(PROGRESS_MAP.LOCALIZE_READY);
                        resolve();
                    });
                });
            }

            /**
             * @private
             */
            _getImagesReadyPromise() {
                return $.ajax({ url: `/img/images-list.json?v=${WavesApp.version}`, dataType: 'json' })
                    .then((list) => {
                        return Promise.all(list.map(AppRun.getLoadImagePromise(list.length)));
                    });
            }

            static getLoadImagePromise(length) {
                return function (path) {
                    return new Promise(resolve => {
                        const img = new Image();
                        const apply = () => {
                            LOADER.addProgress(PROGRESS_MAP.IMAGES_LOADED / length);
                            resolve();
                        };

                        img.onload = apply;
                        img.onerror = () => {
                            console.warn(`Can't load image! "${path}"`);
                            apply();
                        };
                        img.src = path;
                    });
                };
            }

            static _getUrlFromState(state) {
                return (
                    WavesApp
                        .stateTree
                        .getPath(state.name.split('.').slice(-1)[0])
                        .filter((id) => !WavesApp.stateTree.find(id).get('abstract'))
                        .map((id) => WavesApp.stateTree.find(id).get('url') || id)
                        .reduce((url, id) => `${url}/${id}`, '')
                );
            }

        }

        return new AppRun();
    };

    run.$inject = [
        '$rootScope',
        'utils',
        'user',
        '$state',
        'state',
        'modalManager',
        'storage',
        'notification',
        'decorators',
        'waves',
        'ModalRouter',
        'configService',
        'userNotification',
        'whatsNew'
    ];

    angular.module('app')
        .run(run);
})();

/**
 * @property {boolean} $rootScope.Scope#isDesktop
 * @property {boolean} $rootScope.Scope#isNotDesktop
 * @property {boolean} $rootScope.Scope#isPhone
 * @property {boolean} $rootScope.Scope#isNotPhone
 * @property {boolean} $rootScope.Scope#isTablet
 */
<|endoftext|>


<commit_before>// ==UserScript==
// @name        Github Timeline
// @namespace   https://github.com/MyKiwi/github-timeline
// @description Filter your github timeline
// @include     https://github.com/
// @version     1.0
// @updateURL   https://rawgit.com/romqin/github-timeline/master/github-timeline.js
// @run-at      document-end
// @grant       none
// ==/UserScript==

// Main class

githubTimeline = {
    css: {
        dashboard: 'div.container div#dashboard div.news',
        menu: {
            base: 'div#github-timeline-menu',
            child: 'a'
        },

        getMenu: function() {
            'use strict';
            return this.dashboard + ' ' + this.menu.base;
        },

        getItems: function() {
            'use strict';
            return this.getMenu() + ' ' + this.menu.child;
        },

        getItemSelected: function() {
            'use strict';
            return this.getItems() + '.selected';
        }
    },

    template: {
        menu: '' +
            '
' +
            '
' +
            '    All' +
            '    Pull Requests' +
            '    Issues' +
            '    Stars' +
            '    Others' +
            '
' +
            '
'
    },

    menu: {
        select: function(child) {
            'use strict';
            $(githubTimeline.css.getItems() + '.selected').removeClass('selected');
            child.addClass('selected');
            setCookie("ghtl-menu", child.html());
            githubTimeline.dashboard.refresh();
        }
    },

    dashboard: {
        refresh: function() {
            'use strict';
            var $button = $(githubTimeline.css.getItemSelected());

            $dashboard.find('.alert').each(function(index, line) {
                var $line = $(line);
                $line.css('display', 'none');

                var issueRegexp = new RegExp(' issue ', 'g');
                var pullRequestRegexp = new RegExp(' pull request ', 'g');
                switch ($button.html()) {
                    case 'All':
                        $line.css('display', 'block');

                        break;
                    case 'Pull Requests':
                        if (pullRequestRegexp.test($line.find('div.title').html())) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Issues':
                        if (issueRegexp.test($line.find('div.title').html())) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Stars':
                        if ($line.hasClass('watch_started')) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Others':
                        if (!pullRequestRegexp.test($line.find('div.title').html()) && !issueRegexp.test($line.find('div.title').html()) && !$line.hasClass('watch_started')) {
                            $line.css('display', 'block');
                        }

                        break;
                }

            });
        }
    }
};

// Cookie
function setCookie(sName, sValue)
{
    var today = new Date(), expires = new Date();
    expires.setTime(today.getTime() + (365*24*60*60*1000));
    document.cookie = sName + "=" + encodeURIComponent(sValue) + ";expires=" + expires.toGMTString();
}

function getCookie(sName) {
    var oRegex = new RegExp("(?:; )?" + sName + "=([^;]*);?");

    if (oRegex.test(document.cookie)) {
        return decodeURIComponent(RegExp["$1"]);
    }

    return null;
}

// Workflow

window.addEventListener('load', function() {

    $dashboard = $(githubTimeline.css.dashboard);

    $(githubTimeline.template.menu).prependTo($dashboard);
    $menu = $(githubTimeline.css.getMenu());

    $(document).on('click', githubTimeline.css.getItems(), function() {
        githubTimeline.menu.select($(this));
    });

    var menuSelected = getCookie("ghtl-menu");
    if (menuSelected != null) {
        $(githubTimeline.css.getItems()).parent().find('a:contains("' + menuSelected + '")').trigger('click');
    }

    $(document).ajaxComplete(function(event, request, options) {
        var urlMore = /\/dashboard\?page=\d+/g
        if (urlMore.test(options.url)) {
            githubTimeline.dashboard.refresh();
        }
    });

});
<commit_msg>fixed username<commit_after>// ==UserScript==
// @name        Github Timeline
// @namespace   https://github.com/romqin/github-timeline
// @description Filter your github timeline
// @include     https://github.com/
// @version     1.0
// @updateURL   https://rawgit.com/romqin/github-timeline/master/github-timeline.js
// @run-at      document-end
// @grant       none
// ==/UserScript==

// Main class

githubTimeline = {
    css: {
        dashboard: 'div.container div#dashboard div.news',
        menu: {
            base: 'div#github-timeline-menu',
            child: 'a'
        },

        getMenu: function() {
            'use strict';
            return this.dashboard + ' ' + this.menu.base;
        },

        getItems: function() {
            'use strict';
            return this.getMenu() + ' ' + this.menu.child;
        },

        getItemSelected: function() {
            'use strict';
            return this.getItems() + '.selected';
        }
    },

    template: {
        menu: '' +
            '
' +
            '
' +
            '    All' +
            '    Pull Requests' +
            '    Issues' +
            '    Stars' +
            '    Others' +
            '
' +
            '
'
    },

    menu: {
        select: function(child) {
            'use strict';
            $(githubTimeline.css.getItems() + '.selected').removeClass('selected');
            child.addClass('selected');
            setCookie("ghtl-menu", child.html());
            githubTimeline.dashboard.refresh();
        }
    },

    dashboard: {
        refresh: function() {
            'use strict';
            var $button = $(githubTimeline.css.getItemSelected());

            $dashboard.find('.alert').each(function(index, line) {
                var $line = $(line);
                $line.css('display', 'none');

                var issueRegexp = new RegExp(' issue ', 'g');
                var pullRequestRegexp = new RegExp(' pull request ', 'g');
                switch ($button.html()) {
                    case 'All':
                        $line.css('display', 'block');

                        break;
                    case 'Pull Requests':
                        if (pullRequestRegexp.test($line.find('div.title').html())) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Issues':
                        if (issueRegexp.test($line.find('div.title').html())) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Stars':
                        if ($line.hasClass('watch_started')) {
                            $line.css('display', 'block');
                        }

                        break;
                    case 'Others':
                        if (!pullRequestRegexp.test($line.find('div.title').html()) && !issueRegexp.test($line.find('div.title').html()) && !$line.hasClass('watch_started')) {
                            $line.css('display', 'block');
                        }

                        break;
                }

            });
        }
    }
};

// Cookie
function setCookie(sName, sValue)
{
    var today = new Date(), expires = new Date();
    expires.setTime(today.getTime() + (365*24*60*60*1000));
    document.cookie = sName + "=" + encodeURIComponent(sValue) + ";expires=" + expires.toGMTString();
}

function getCookie(sName) {
    var oRegex = new RegExp("(?:; )?" + sName + "=([^;]*);?");

    if (oRegex.test(document.cookie)) {
        return decodeURIComponent(RegExp["$1"]);
    }

    return null;
}

// Workflow

window.addEventListener('load', function() {

    $dashboard = $(githubTimeline.css.dashboard);

    $(githubTimeline.template.menu).prependTo($dashboard);
    $menu = $(githubTimeline.css.getMenu());

    $(document).on('click', githubTimeline.css.getItems(), function() {
        githubTimeline.menu.select($(this));
    });

    var menuSelected = getCookie("ghtl-menu");
    if (menuSelected != null) {
        $(githubTimeline.css.getItems()).parent().find('a:contains("' + menuSelected + '")').trigger('click');
    }

    $(document).ajaxComplete(function(event, request, options) {
        var urlMore = /\/dashboard\?page=\d+/g
        if (urlMore.test(options.url)) {
            githubTimeline.dashboard.refresh();
        }
    });

});
<|endoftext|>