<commit_before>(function ($) {
    "use strict";
	var filterRepos = function (id) {
		var filter = $('#' + id + '-filter input').val().toLowerCase();
		if (filter === '') {
			$('.tab-pane#' + id + ' .repo').show();
		} else {
			$('.tab-pane#' + id + ' .repo').each(function (idx, elem) {
				if ($(elem).attr('id').toLowerCase().indexOf(filter) !== -1) {
					$(elem).show();
				} else {
					$(elem).hide();
				}
			});
		}
	},
        selectBranch = function () { //CohortExDev - selectBranch defines where to go
            Stevenson.Account.repo = $('#current-repo').html();
            Stevenson.Account.branch = $('#branches').val();
            Stevenson.Account.save();

			//CohortExDev - Go to studies folder on repo=master (was: /cms/site.html#)
			Stevenson.repo.getLayoutsAndSchemas({
                success: function (branches) {
					if (Stevenson.ext.type == 'study') {
                    	window.location = Stevenson.Account.siteBaseURL + '/cohortexCms/cohortex_siteStudies.html#' + Stevenson.Account.studiesPath ;
					} else {
                    	window.location = Stevenson.Account.siteBaseURL + '/cohortexCms/cohortex_sitePosts.html#' + Stevenson.Account.subFolder + '_posts' ;
					}
                },
                error: function (err) {
					Stevenson.ui.Messages.displayError('Unable to load layouts: '
                            + err);
                    Stevenson.ui.Messages.displayError('Unable to load schemas: '
                            + err);
                }
            });

            return false;
        },
        loadRepos = function (group) {
            Stevenson.ui.Loader.display('Loading repositories...', 100);
            Stevenson.log.info('Loading repositories for ' + group);
            Stevenson.repo.getRepos({
                group: group,
                success: function (repos) {
                    var container = $('.tab-content #mine'),
                        validRepo = false,
                        forksRepo = [],
                        forksCount = 0;

                    if (group) {
                        container = $('.tab-content #' + group);
                    }

                    $.each(repos, function (index, repo) {
                        var lastRepo = (index === repos.length - 1);
						//CohortExDev - Just accept repositories forked from forkRootName as parent
                        if (repo.fork === true) {
                            forksRepo.push(repo);
                        }
                        if (lastRepo === true) {
                            if (forksRepo.length > 0) {
                                forksCount = forksRepo.length;
                                forksRepo[forksRepo.length - 1].lastRepo = true;

								//CohortExDev - For each repo, built the intem (pencil and link)
                                $.each(forksRepo, function (index, forkedRepo) {
                                    Stevenson.repo.getRepo({
                                        name: forkedRepo.full_name,
                                        success: function (forkedRepo) {
                                            forksCount -= 1;
                                            if (forkedRepo.source.name === Stevenson.Account.forkRootName) {
                                                validRepo = true;
                                                container.mustache('repo-item', forkedRepo);

                                                Stevenson.ui.Loader.hide();
                                                container.find('a.open').click(function () {
                                                    Stevenson.ui.Loader.display('Loading branches...', 100);
                                                    var repo = $(this).attr('data-repo');
                                                    Stevenson.repo.getBranches({
                                                        repoName: repo,
                                                        success: function (branches) {
                                                            Stevenson.log.debug('Loaded branches: ' + branches);
                                                            $('#branches').html('');
                                                            $.each(branches, function (index, branch) {
                                                                $('#branches').append('<option value="' + branch + '">' + branch + '</option>');
                                                            });
                                                            $('#current-repo').html(repo);

															//CohortExDev -Force master branch unless there is no master branch
                                                            if (branches.length !== 1 && branches.indexOf('master') < 0) {
                                                                Stevenson.ui.Loader.hide();
                                                                $('#branch-modal').modal('show');
                                                            } else {
																if (branches.indexOf('master') > 0) {
																	$('#branches').val('master');
																}

																//CohortExDev - selectBranch defines where to go
                                                                selectBranch();
                                                            }
                                                        },
                                                        error: function (err) {
                                                            Stevenson.ui.Messages.displayError('Unable to load branches: '
                                                                + err);
                                                            Stevenson.ui.Loader.hide();
                                                        }
                                                    });
                                                    return false;
                                                });
                                            } else {
                                                if (forksCount === 0 && validRepo === false) {
                                                    Stevenson.ui.Messages.displayError('None of your repositories in this group is a direct or indirect fork from MTFA/CoortEx source ');
                                                    Stevenson.ui.Loader.hide();
                                                }
                                            }
                                        },
                                        error: function (message) {
                                            Stevenson.ui.Loader.hide();
                                            Stevenson.ui.Messages.displayError('Unable to load repositories: '
                                                    + message);
                                        }
                                    });
                                });
                            } else {
                                Stevenson.ui.Messages.displayError('None of your repositories in this group is a direct or indirect fork from MTFA/CohortEx source ');
                                Stevenson.ui.Loader.hide();
                            }

                        }
                    });
                },
                error: function (message) {
                    Stevenson.ui.Loader.hide();
					isLoading = false;
                    Stevenson.ui.Messages.displayError('Unable to load repositories: '
                            + message);
                }
            });
        };
	Stevenson.ext.afterInit(function () {

		//CohortExDev - Select if study or post
		Stevenson.ext.type = Stevenson.util.getParameter('type');
		if(Stevenson.ext.type == '') {
			Stevenson.ext.type = 'study';
		}
		//Set the corresponding title
		$('select-title').html(Stevenson.ext.type);
		Stevenson.ui.Loader.display('Loading organizations...', 100);
		Stevenson.repo.getOrgs({
			success: function (orgs) {
				$.each(orgs, function (idx, org) {
					$('.nav-tabs').append('
' + org.login + '
');
					$('.nav-tabs a[href=#' + org.login + ']').click(function () {
						if ($('.tab-pane#' + org.login).html() === '') {
							$('#' + org.login).mustache('org-header', org);
							loadRepos(org.login);
							var filterRepo = function () {
								filterRepos(org.login);
							};
							$('#' + org.login + '-filter input').change(filterRepo).keyup(filterRepo).click(filterRepo).focusout(filterRepo);
							$('#' + org.login + '-filter').submit(function () {
								return false;
							});
						}
						$(this).tab('show');
						return false;
					});
					$('.repos').append('

');
				});
				Stevenson.ui.Loader.hide();
				loadRepos();
				$('.nav-tabs a[href=#mine]').click(function () {
					$(this).tab('show');
					return false;
				});
			},
			error: function (message) {
				Stevenson.ui.Loader.hide();
				Stevenson.ui.Messages.displayError('Unable to load groups: '
						+ message);
			}
		});
		var user = Stevenson.session.get('user'),
            filterRepo = function () {
                filterRepos('mine');
            };
		$('#user-avatar').attr('src', user.avatar_url);
		$('#mine-filter input').change(filterRepo).keyup(filterRepo).click(filterRepo).focusout(filterRepo);

	});
	$(document).ready(function () {
		$('#branch-modal .btn').click(selectBranch);
	});
}(jQuery));
<commit_msg>- Test<commit_after>(function ($) {
    "use strict";
	var filterRepos = function (id) {
		var filter = $('#' + id + '-filter input').val().toLowerCase();
		if (filter === '') {
			$('.tab-pane#' + id + ' .repo').show();
		} else {
			$('.tab-pane#' + id + ' .repo').each(function (idx, elem) {
				if ($(elem).attr('id').toLowerCase().indexOf(filter) !== -1) {
					$(elem).show();
				} else {
					$(elem).hide();
				}
			});
		}
	},
        selectBranch = function () { //CohortExDev - selectBranch defines where to go
            Stevenson.Account.repo = $('#current-repo').html();
            Stevenson.Account.branch = $('#branches').val();
            Stevenson.Account.save();

			//CohortExDev - Go to studies folder on repo=master (was: /cms/site.html#)
			Stevenson.repo.getLayoutsAndSchemas({
                success: function (branches) {
					if (Stevenson.ext.type == 'study') {
                    	window.location = Stevenson.Account.siteBaseURL + '/cohortexCms/cohortex_siteStudies.html#' + Stevenson.Account.studiesPath ;
					} else {
                    	window.location = Stevenson.Account.siteBaseURL + '/cohortexCms/cohortex_sitePosts.html#' + Stevenson.Account.subFolder + '_posts' ;
					}
                },
                error: function (err) {
					Stevenson.ui.Messages.displayError('Unable to load layouts: '
                            + err);
                    Stevenson.ui.Messages.displayError('Unable to load schemas: '
                            + err);
                }
            });

            return false;
        },
        loadRepos = function (group) {
            Stevenson.ui.Loader.display('Loading repositories...', 100);
            Stevenson.log.info('Loading repositories for ' + group);
            Stevenson.repo.getRepos({
                group: group,
                success: function (repos) {
                    var container = $('.tab-content #mine'),
                        validRepo = false,
                        forksRepo = [],
                        forksCount = 0;

                    if (group) {
                        container = $('.tab-content #' + group);
                    }

                    $.each(repos, function (index, repo) {
                        var lastRepo = (index === repos.length - 1);
						//CohortExDev - Just accept repositories forked from forkRootName as parent
                        if (repo.fork === true) {
                            forksRepo.push(repo);
                        }
                        if (lastRepo === true) {
                            if (forksRepo.length > 0) {
                                forksCount = forksRepo.length;
                                forksRepo[forksRepo.length - 1].lastRepo = true;

								//CohortExDev - For each repo, built the intem (pencil and link)
                                $.each(forksRepo, function (index, forkedRepo) {
                                    Stevenson.repo.getRepo({
                                        name: forkedRepo.full_name,
                                        success: function (forkedRepo) {
                                            forksCount -= 1;
                                            if (forkedRepo.source.name === Stevenson.Account.forkRootName) {
                                                validRepo = true;
                                                container.mustache('repo-item', forkedRepo);

                                                Stevenson.ui.Loader.hide();
                                                container.find('a.open').click(function () {
                                                    Stevenson.ui.Loader.display('Loading branches...', 100);
                                                    var repo = $(this).attr('data-repo');
                                                    Stevenson.repo.getBranches({
                                                        repoName: repo,
                                                        success: function (branches) {
                                                            Stevenson.log.debug('Loaded branches: ' + branches);
                                                            $('#branches').html('');
                                                            $.each(branches, function (index, branch) {
                                                                $('#branches').append('<option value="' + branch + '">' + branch + '</option>');
                                                            });
                                                            $('#current-repo').html(repo);

															//CohortExDev -Force master branch unless there is no master branch
                                                            if (branches.length !== 1 && branches.indexOf('master') < 0) {
                                                                Stevenson.ui.Loader.hide();
                                                                $('#branch-modal').modal('show');
                                                            } else {
																if (branches.indexOf('master') > 0) {
																	$('#branches').val('master');
																}

																//CohortExDev - selectBranch defines where to go
                                                                selectBranch();
                                                            }
                                                        },
                                                        error: function (err) {
                                                            Stevenson.ui.Messages.displayError('Unable to load branches: '
                                                                + err);
                                                            Stevenson.ui.Loader.hide();
                                                        }
                                                    });
                                                    return false;
                                                });
                                            } else {
                                                if (forksCount === 0 && validRepo === false) {
                                                    Stevenson.ui.Messages.displayError('None of your repositories in this group is a direct or indirect fork from MTFA/CoortEx source ');
                                                    Stevenson.ui.Loader.hide();
                                                }
                                            }
                                        },
                                        error: function (message) {
                                            Stevenson.ui.Loader.hide();
                                            Stevenson.ui.Messages.displayError('Unable to load repositories: '
                                                    + message);
                                        }
                                    });
                                });
                            } else {
                                Stevenson.ui.Messages.displayError('None of your repositories in this group is a direct or indirect fork from MTFA/CohortEx source ');
                                Stevenson.ui.Loader.hide();
                            }

                        }
                    });
                },
                error: function (message) {
                    Stevenson.ui.Loader.hide();
					isLoading = false;
                    Stevenson.ui.Messages.displayError('Unable to load repositories: '
                            + message);
                }
            });
        };
	Stevenson.ext.afterInit(function () {

		//CohortExDev - Select if study or post
		Stevenson.ext.type = Stevenson.util.getParameter('type');
		if(Stevenson.ext.type == '') {
			Stevenson.ext.type = 'study';
		}
		//Set the corresponding title
		$('select-title').innerHTML = Stevenson.ext.type;

		Stevenson.ui.Loader.display('Loading organizations...', 100);
		Stevenson.repo.getOrgs({
			success: function (orgs) {
				$.each(orgs, function (idx, org) {
					$('.nav-tabs').append('
' + org.login + '
');
					$('.nav-tabs a[href=#' + org.login + ']').click(function () {
						if ($('.tab-pane#' + org.login).html() === '') {
							$('#' + org.login).mustache('org-header', org);
							loadRepos(org.login);
							var filterRepo = function () {
								filterRepos(org.login);
							};
							$('#' + org.login + '-filter input').change(filterRepo).keyup(filterRepo).click(filterRepo).focusout(filterRepo);
							$('#' + org.login + '-filter').submit(function () {
								return false;
							});
						}
						$(this).tab('show');
						return false;
					});
					$('.repos').append('

');
				});
				Stevenson.ui.Loader.hide();
				loadRepos();
				$('.nav-tabs a[href=#mine]').click(function () {
					$(this).tab('show');
					return false;
				});
			},
			error: function (message) {
				Stevenson.ui.Loader.hide();
				Stevenson.ui.Messages.displayError('Unable to load groups: '
						+ message);
			}
		});
		var user = Stevenson.session.get('user'),
            filterRepo = function () {
                filterRepos('mine');
            };
		$('#user-avatar').attr('src', user.avatar_url);
		$('#mine-filter input').change(filterRepo).keyup(filterRepo).click(filterRepo).focusout(filterRepo);

	});
	$(document).ready(function () {
		$('#branch-modal .btn').click(selectBranch);
	});
}(jQuery));
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

const {actionTypes: at} = Cu.import("resource://activity-stream/common/Actions.jsm", {});

const {shortURL} = Cu.import("resource://activity-stream/lib/ShortURL.jsm", {});
const {SectionsManager} = Cu.import("resource://activity-stream/lib/SectionsManager.jsm", {});
const {TOP_SITES_DEFAULT_ROWS, TOP_SITES_MAX_SITES_PER_ROW} = Cu.import("resource://activity-stream/common/Reducers.jsm", {});
const {Dedupe} = Cu.import("resource://activity-stream/common/Dedupe.jsm", {});

XPCOMUtils.defineLazyModuleGetter(this, "filterAdult",
  "resource://activity-stream/lib/FilterAdult.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LinksCache",
  "resource://activity-stream/lib/LinksCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
  "resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Screenshots",
  "resource://activity-stream/lib/Screenshots.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
  "resource://gre/modules/PageThumbs.jsm");

const HIGHLIGHTS_MAX_LENGTH = 9;
const MANY_EXTRA_LENGTH = HIGHLIGHTS_MAX_LENGTH * 5 + TOP_SITES_DEFAULT_ROWS * TOP_SITES_MAX_SITES_PER_ROW;
const SECTION_ID = "highlights";

this.HighlightsFeed = class HighlightsFeed {
  constructor() {
    this.dedupe = new Dedupe(this._dedupeKey);
    this.linksCache = new LinksCache(NewTabUtils.activityStreamLinks,
      "getHighlights", ["image"]);
    PageThumbs.addExpirationFilter(this);
  }

  _dedupeKey(site) {
    // Treat bookmarks as un-dedupable, otherwise show one of a url
    return site && (site.type === "bookmark" ? {} : site.url);
  }

  init() {
    SectionsManager.onceInitialized(this.postInit.bind(this));
  }

  postInit() {
    SectionsManager.enableSection(SECTION_ID);
    this.fetchHighlights({broadcast: true});
  }

  uninit() {
    SectionsManager.disableSection(SECTION_ID);
    PageThumbs.removeExpirationFilter(this);
  }

  filterForThumbnailExpiration(callback) {
    const sectionIndex = SectionsManager.sections.get(SECTION_ID).order;
    const state = this.store.getState().Sections[sectionIndex];

    callback(state && state.initialized ? state.rows.reduce((acc, site) => {
      // Screenshots call in `fetchImage` will search for preview_image_url or
      // fallback to URL, so we prevent both from being expired.
      acc.push(site.url);
      if (site.preview_image_url) {
        acc.push(site.preview_image_url);
      }
      return acc;
    }, []) : []);
  }

  /**
   * Refresh the highlights data for content.
   * @param {bool} options.broadcast Should the update be broadcasted.
   */
  async fetchHighlights(options = {}) {
    // We need TopSites for deduping, so wait for TOP_SITES_UPDATED.
    if (!this.store.getState().TopSites.initialized) {
      return;
    }

    // We broadcast when we want to force an update, so get fresh links
    if (options.broadcast) {
      this.linksCache.expire();
    }

    // Request more than the expected length to allow for items being removed by
    // deduping against Top Sites or multiple history from the same domain, etc.
    const manyPages = await this.linksCache.request({numItems: MANY_EXTRA_LENGTH});

    // Remove adult highlights if we need to
    const checkedAdult = this.store.getState().Prefs.values.filterAdult ?
      filterAdult(manyPages) : manyPages;

    // Remove any Highlights that are in Top Sites already
    const [, deduped] = this.dedupe.group(this.store.getState().TopSites.rows, checkedAdult);

    // Keep all "bookmark"s and at most one (most recent) "history" per host
    const highlights = [];
    const hosts = new Set();
    for (const page of deduped) {
      const hostname = shortURL(page);
      // Skip this history page if we already something from the same host
      if (page.type === "history" && hosts.has(hostname)) {
        continue;
      }

      // If we already have the image for the card, use that immediately. Else
      // asynchronously fetch the image.
      if (!page.image) {
        this.fetchImage(page);
      }

      // We want the page, so update various fields for UI
      Object.assign(page, {
        hasImage: true, // We always have an image - fall back to a screenshot
        hostname,
        type: page.bookmarkGuid ? "bookmark" : page.type
      });

      // Add the "bookmark" or not-skipped "history"
      highlights.push(page);
      hosts.add(hostname);

      // Remove internal properties that might be updated after dispatch
      delete page.__sharedCache;

      // Skip the rest if we have enough items
      if (highlights.length === HIGHLIGHTS_MAX_LENGTH) {
        break;
      }
    }

    const sectionIndex = SectionsManager.sections.get(SECTION_ID).order;
    const {initialized} = this.store.getState().Sections[sectionIndex];
    // Broadcast when required or if it is the first update.
    const shouldBroadcast = options.broadcast || !initialized;

    SectionsManager.updateSection(SECTION_ID, {rows: highlights}, shouldBroadcast);
  }

  /**
   * Fetch an image for a given highlight and update the card with it. If no
   * image is available then fallback to fetching a screenshot.
   */
  fetchImage(page) {
    // Request a screenshot if we don't already have one pending
    const {preview_image_url: imageUrl, url} = page;
    Screenshots.maybeCacheScreenshot(page, imageUrl || url, "image", image => {
      SectionsManager.updateSectionCard(SECTION_ID, url, {image}, true);
    });
  }

  onAction(action) {
    switch (action.type) {
      case at.INIT:
        this.init();
        break;
      case at.SYSTEM_TICK:
        this.fetchHighlights({broadcast: false});
        break;
      case at.MIGRATION_COMPLETED:
      case at.PLACES_HISTORY_CLEARED:
      case at.PLACES_LINKS_DELETED:
      case at.PLACES_LINK_BLOCKED:
        this.fetchHighlights({broadcast: true});
        break;
      case at.PLACES_BOOKMARK_ADDED:
      case at.PLACES_BOOKMARK_REMOVED:
        this.linksCache.expire();
        this.fetchHighlights({broadcast: false});
        break;
      case at.TOP_SITES_UPDATED:
        this.fetchHighlights({broadcast: false});
        break;
      case at.UNINIT:
        this.uninit();
        break;
    }
  }
};

this.EXPORTED_SYMBOLS = ["HighlightsFeed", "SECTION_ID"];
<commit_msg>chore(mc): Backport changes from Bug 1425496<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";

const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");

const {actionTypes: at} = Cu.import("resource://activity-stream/common/Actions.jsm", {});

const {shortURL} = Cu.import("resource://activity-stream/lib/ShortURL.jsm", {});
const {SectionsManager} = Cu.import("resource://activity-stream/lib/SectionsManager.jsm", {});
const {TOP_SITES_DEFAULT_ROWS, TOP_SITES_MAX_SITES_PER_ROW} = Cu.import("resource://activity-stream/common/Reducers.jsm", {});
const {Dedupe} = Cu.import("resource://activity-stream/common/Dedupe.jsm", {});

XPCOMUtils.defineLazyModuleGetter(this, "filterAdult",
  "resource://activity-stream/lib/FilterAdult.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "LinksCache",
  "resource://activity-stream/lib/LinksCache.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "NewTabUtils",
  "resource://gre/modules/NewTabUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Screenshots",
  "resource://activity-stream/lib/Screenshots.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "PageThumbs",
  "resource://gre/modules/PageThumbs.jsm");

const HIGHLIGHTS_MAX_LENGTH = 9;
const MANY_EXTRA_LENGTH = HIGHLIGHTS_MAX_LENGTH * 5 + TOP_SITES_DEFAULT_ROWS * TOP_SITES_MAX_SITES_PER_ROW;
const SECTION_ID = "highlights";

this.HighlightsFeed = class HighlightsFeed {
  constructor() {
    this.dedupe = new Dedupe(this._dedupeKey);
    this.linksCache = new LinksCache(NewTabUtils.activityStreamLinks,
      "getHighlights", ["image"]);
    PageThumbs.addExpirationFilter(this);
  }

  _dedupeKey(site) {
    // Treat bookmarks as un-dedupable, otherwise show one of a url
    return site && (site.type === "bookmark" ? {} : site.url);
  }

  init() {
    SectionsManager.onceInitialized(this.postInit.bind(this));
  }

  postInit() {
    SectionsManager.enableSection(SECTION_ID);
    this.fetchHighlights({broadcast: true});
  }

  uninit() {
    SectionsManager.disableSection(SECTION_ID);
    PageThumbs.removeExpirationFilter(this);
  }

  filterForThumbnailExpiration(callback) {
    const sectionIndex = SectionsManager.sections.get(SECTION_ID).order;
    const state = this.store.getState().Sections[sectionIndex];

    callback(state && state.initialized ? state.rows.reduce((acc, site) => {
      // Screenshots call in `fetchImage` will search for preview_image_url or
      // fallback to URL, so we prevent both from being expired.
      acc.push(site.url);
      if (site.preview_image_url) {
        acc.push(site.preview_image_url);
      }
      return acc;
    }, []) : []);
  }

  /**
   * Refresh the highlights data for content.
   * @param {bool} options.broadcast Should the update be broadcasted.
   */
  async fetchHighlights(options = {}) {
    // We need TopSites for deduping, so wait for TOP_SITES_UPDATED.
    if (!this.store.getState().TopSites.initialized) {
      return;
    }

    // We broadcast when we want to force an update, so get fresh links
    if (options.broadcast) {
      this.linksCache.expire();
    }

    // Request more than the expected length to allow for items being removed by
    // deduping against Top Sites or multiple history from the same domain, etc.
    // Until bug 1425496 lands, do not include saved Pocket items in highlights
    const manyPages = await this.linksCache.request({numItems: MANY_EXTRA_LENGTH, excludePocket: true});

    // Remove adult highlights if we need to
    const checkedAdult = this.store.getState().Prefs.values.filterAdult ?
      filterAdult(manyPages) : manyPages;

    // Remove any Highlights that are in Top Sites already
    const [, deduped] = this.dedupe.group(this.store.getState().TopSites.rows, checkedAdult);

    // Keep all "bookmark"s and at most one (most recent) "history" per host
    const highlights = [];
    const hosts = new Set();
    for (const page of deduped) {
      const hostname = shortURL(page);
      // Skip this history page if we already something from the same host
      if (page.type === "history" && hosts.has(hostname)) {
        continue;
      }

      // If we already have the image for the card, use that immediately. Else
      // asynchronously fetch the image.
      if (!page.image) {
        this.fetchImage(page);
      }

      // We want the page, so update various fields for UI
      Object.assign(page, {
        hasImage: true, // We always have an image - fall back to a screenshot
        hostname,
        type: page.bookmarkGuid ? "bookmark" : page.type
      });

      // Add the "bookmark" or not-skipped "history"
      highlights.push(page);
      hosts.add(hostname);

      // Remove internal properties that might be updated after dispatch
      delete page.__sharedCache;

      // Skip the rest if we have enough items
      if (highlights.length === HIGHLIGHTS_MAX_LENGTH) {
        break;
      }
    }

    const sectionIndex = SectionsManager.sections.get(SECTION_ID).order;
    const {initialized} = this.store.getState().Sections[sectionIndex];
    // Broadcast when required or if it is the first update.
    const shouldBroadcast = options.broadcast || !initialized;

    SectionsManager.updateSection(SECTION_ID, {rows: highlights}, shouldBroadcast);
  }

  /**
   * Fetch an image for a given highlight and update the card with it. If no
   * image is available then fallback to fetching a screenshot.
   */
  fetchImage(page) {
    // Request a screenshot if we don't already have one pending
    const {preview_image_url: imageUrl, url} = page;
    Screenshots.maybeCacheScreenshot(page, imageUrl || url, "image", image => {
      SectionsManager.updateSectionCard(SECTION_ID, url, {image}, true);
    });
  }

  onAction(action) {
    switch (action.type) {
      case at.INIT:
        this.init();
        break;
      case at.SYSTEM_TICK:
        this.fetchHighlights({broadcast: false});
        break;
      case at.MIGRATION_COMPLETED:
      case at.PLACES_HISTORY_CLEARED:
      case at.PLACES_LINKS_DELETED:
      case at.PLACES_LINK_BLOCKED:
        this.fetchHighlights({broadcast: true});
        break;
      case at.PLACES_BOOKMARK_ADDED:
      case at.PLACES_BOOKMARK_REMOVED:
        this.linksCache.expire();
        this.fetchHighlights({broadcast: false});
        break;
      case at.TOP_SITES_UPDATED:
        this.fetchHighlights({broadcast: false});
        break;
      case at.UNINIT:
        this.uninit();
        break;
    }
  }
};

this.EXPORTED_SYMBOLS = ["HighlightsFeed", "SECTION_ID"];
<|endoftext|>


<commit_before>var filesToLoad = [
  "canvas/init.js",
  "canvas/utils/configure.js",
  "canvas/utils/deconfigure.js",
  "canvas/utils/resize.js",
  "canvas/utils/coordinates.js",
  "draw/init.js",
  "draw/colors/fill.js",
  "draw/colors/stroke.js",
  "draw/colors/nostroke.js",
  "draw/colors/nofill.js",
  "draw/colors/getfill.js",
  "draw/colors/getstroke.js",
  "draw/settings/strokeweight.js",
  "draw/settings/getstrokeweight.js",
  "draw/settings/rectmode.js",
  "draw/settings/ellipsemode.js",
  "draw/settings/imagemode.js",
  "draw/settings/getrectmode.js",
  "draw/settings/getellipsemode.js",
  "draw/settings/getimagemode.js",
  "draw/settings/strokejoin.js",
  "draw/settings/strokecap.js",
  "draw/settings/getstrokejoin.js",
  "draw/settings/getstrokecap.js",
  "draw/settings/textfont.js",
  "draw/settings/gettextfont.js",
  "draw/settings/textsize.js",
  "draw/settings/gettextsize.js",
  "draw/shapes/arc.js",
  "draw/shapes/background.js",
  "draw/shapes/beginshape.js",
  "draw/shapes/beziervertex.js",
  "draw/shapes/ellipse.js",
  "draw/shapes/endshape.js",
  "draw/shapes/line.js",
  "draw/shapes/point.js",
  "draw/shapes/poly.js",
  "draw/shapes/quadvertex.js",
  "draw/shapes/rect.js",
  "draw/shapes/text.js",
  "draw/shapes/vertex.js",
  "draw/image/images.js",
  "draw/image/loadimage.js",
  "draw/image/loadimageset.js",
  "draw/image/image.js",
  "draw/image/get.js",
  "physics/init.js",
  "physics/minilibs/equation.js",
  "physics/minilibs/vector2.js",
  "physics/minilibs/collisiondetection.js",
  "physics/entities/circle.js",
  "physics/entities/line.js",
  "physics/entities/constraints/constraint.js",
  "physics/entities/constraints/bungee.js",
  "physics/entities/constraints/compressor.js",
  "physics/entities/constraints/cord.js",
  "physics/entities/constraints/extender.js",
  "physics/entities/constraints/rod.js",
  "physics/entities/constraints/spring.js",
];

function load(onFinish, override) {
  if(KAPhy.version === KAPhy.current) {
    if(onFinish) onFinish();
    return;
  }

  function importJS(filename, onLoad) {
    var newScript = document.createElement("script");

    newScript.type = "text/javascript";
    newScript.src = "https://rawgit.com/TemporalFuzz/KAPhy/master/" + filename;

    newScript.onload = onLoad;

    document.head.appendChild(newScript);
  }

  var i = 0;
  function loadNext() {
    i++;
    console.log((i + 1) + " files loaded!");
    if (i >= filesToLoad.length) {
      KAPhy.finishUpdate();
      if (onFinish) onFinish();
      return;
    }
    importJS(filesToLoad[i], loadNext);
  };
  importJS(filesToLoad[i], loadNext);
}
<commit_msg>Update init.js<commit_after>var filesToLoad = [
  "canvas/init.js",
  "canvas/utils/configure.js",
  "canvas/utils/deconfigure.js",
  "canvas/utils/resize.js",
  "canvas/utils/coordinates.js",
  "draw/init.js",
  "draw/colors/fill.js",
  "draw/colors/stroke.js",
  "draw/colors/nostroke.js",
  "draw/colors/nofill.js",
  "draw/colors/getfill.js",
  "draw/colors/getstroke.js",
  "draw/settings/strokeweight.js",
  "draw/settings/getstrokeweight.js",
  "draw/settings/rectmode.js",
  "draw/settings/ellipsemode.js",
  "draw/settings/imagemode.js",
  "draw/settings/getrectmode.js",
  "draw/settings/getellipsemode.js",
  "draw/settings/getimagemode.js",
  "draw/settings/strokejoin.js",
  "draw/settings/strokecap.js",
  "draw/settings/getstrokejoin.js",
  "draw/settings/getstrokecap.js",
  "draw/settings/textfont.js",
  "draw/settings/gettextfont.js",
  "draw/settings/textsize.js",
  "draw/settings/gettextsize.js",
  "draw/transform/popmatrix.js",
  "draw/transform/pushmatrix.js",
  "draw/transform/rotate.js",
  "draw/transform/scale.js",
  "draw/transform/skew.js",
  "draw/transform/translate.js",
  "draw/shapes/arc.js",
  "draw/shapes/background.js",
  "draw/shapes/beginshape.js",
  "draw/shapes/beziervertex.js",
  "draw/shapes/ellipse.js",
  "draw/shapes/endshape.js",
  "draw/shapes/line.js",
  "draw/shapes/point.js",
  "draw/shapes/poly.js",
  "draw/shapes/quadvertex.js",
  "draw/shapes/rect.js",
  "draw/shapes/text.js",
  "draw/shapes/vertex.js",
  "draw/image/images.js",
  "draw/image/loadimage.js",
  "draw/image/loadimageset.js",
  "draw/image/image.js",
  "draw/image/get.js",
  "physics/init.js",
  "physics/minilibs/equation.js",
  "physics/minilibs/vector2.js",
  "physics/minilibs/collisiondetection.js",
  "physics/entities/circle.js",
  "physics/entities/line.js",
  "physics/entities/constraints/constraint.js",
  "physics/entities/constraints/bungee.js",
  "physics/entities/constraints/compressor.js",
  "physics/entities/constraints/cord.js",
  "physics/entities/constraints/extender.js",
  "physics/entities/constraints/rod.js",
  "physics/entities/constraints/spring.js",
];

function load(onFinish, override) {
  if(KAPhy.version === KAPhy.current) {
    if(onFinish) onFinish();
    return;
  }

  function importJS(filename, onLoad) {
    var newScript = document.createElement("script");

    newScript.type = "text/javascript";
    newScript.src = "https://rawgit.com/TemporalFuzz/KAPhy/master/" + filename;

    newScript.onload = onLoad;

    document.head.appendChild(newScript);
  }

  var i = 0;
  function loadNext() {
    i++;
    console.log((i + 1) + " files loaded!");
    if (i >= filesToLoad.length) {
      KAPhy.finishUpdate();
      if (onFinish) onFinish();
      return;
    }
    importJS(filesToLoad[i], loadNext);
  };
  importJS(filesToLoad[i], loadNext);
}
<|endoftext|>


<commit_before>import Link from 'next/link';
import * as React from 'react';
import { css } from 'react-emotion';

import * as Constants from '~/common/constants';
import BrandLogo from '~/components/icons/BrandLogo';
import DismissIcon from '~/components/icons/DismissIcon';
import MenuIcon from '~/components/icons/Menu';
import AlgoliaSearch from '~/components/plugins/AlgoliaSearch';

const STYLES_LOGO = css`
  display: flex;
`;

const STYLES_LEFT = css`
  flex-shrink: 0;
  padding-right: 24px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
`;

const STYLES_RIGHT = css`
  min-width: 5%;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
`;

const STYLES_LOGO_CONTAINER = css`
  display: flex;
  flex-direction: row;
  align-items: center;
  padding-top: 8px;
`;

const STYLES_NAV = css`
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 58px;
  width: 100%;
  padding: 0 24px 0 24px;

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    padding: 0 16px 0 16px;
  }
`;

const STYLES_TITLE_TEXT = css`
  white-space: nowrap;
  padding: 0 0 0 8px;
  font-size: 1.3rem;
  display: flex;
  padding-bottom: 2px;
  font-family: ${Constants.fonts.demi};

  @media screen and (max-width: 400px) {
    display: none;
  }
`;

const STYLES_MENU_BUTTON = css`
  cursor: pointer;
  height: 100%;
  align-items: center;
  justify-content: center;
  padding-left: 24px;
  margin-left: 16px;
  border-left: 1px solid ${Constants.colors.border};
  text-decoration: none;
  color: ${Constants.colors.black};

  :visited {
    color: ${Constants.colors.black};
  }

  :hover {
    color: ${Constants.colors.expo};
  }

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    padding-left: 16px;
  }
`;

const STYLES_MENU_BUTTON_IS_MOBILE = css`
  display: none;

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    display: flex;
  }
`;

const STYLES_MENU_BUTTON_VISIBLE = css`
  display: flex;
`;

const SECTION_LINK_CONTAINER = css`
  display: flex;
`;

const SECTION_LINK = css`
  text-decoration: none;
  font-weight: 900;
  font-family: expo-brand-demi, sans-serif;
  :hover {
    opacity: 0.5;
  }
`;

const SECTION_LINK_ACTIVE = css`
  text-decoration: underline;
`;

const SECTION_LINK_INACTIVE = css`
  color: #000 !important;
`;

function SectionContainer({ spaceBetween = 0, spaceAround = 0, children, style }) {
  return (

      {children.map((child, i) => (

          {child}

      ))}

  );
}

export default class DocumentationHeader extends React.PureComponent {
  render() {
    return (

            <Link href="/versions/">

                <BrandLogo />

            </Link>

Expo

            <SectionContainer
              spaceBetween={15}
              style={{
                paddingLeft: 10,
                marginLeft: 15,
                borderLeftWidth: 1,
                borderLeftColor: '#eee',
                borderLeftStyle: 'solid',
              }}>
              <Link href="/">

                  Get Started

              </Link>
              <Link href="/guides">

                  Guides

              </Link>
              <Link href="/versions/latest/">

                  API Reference

              </Link>
            </SectionContainer>

          {!this.props.isAlogliaSearchHidden && (
            <AlgoliaSearch router={this.props.router} version={this.props.version} />
          )}

          {!this.props.isMenuActive && (
            <span
              className={`${STYLES_MENU_BUTTON} ${STYLES_MENU_BUTTON_IS_MOBILE}`}
              onClick={this.props.onShowMenu}>
              <MenuIcon />

          )}

          {this.props.isMenuActive && (
            <span
              className={`${STYLES_MENU_BUTTON} ${STYLES_MENU_BUTTON_VISIBLE}`}
              onClick={this.props.onHideMenu}>
              <DismissIcon />

          )}

    );
  }
}
<commit_msg>[docs] Change the top-left header link to go back to /<commit_after>import Link from 'next/link';
import * as React from 'react';
import { css } from 'react-emotion';

import * as Constants from '~/common/constants';
import BrandLogo from '~/components/icons/BrandLogo';
import DismissIcon from '~/components/icons/DismissIcon';
import MenuIcon from '~/components/icons/Menu';
import AlgoliaSearch from '~/components/plugins/AlgoliaSearch';

const STYLES_LOGO = css`
  display: flex;
`;

const STYLES_LEFT = css`
  flex-shrink: 0;
  padding-right: 24px;
  display: flex;
  align-items: center;
  justify-content: flex-end;
`;

const STYLES_RIGHT = css`
  min-width: 5%;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: flex-end;
`;

const STYLES_LOGO_CONTAINER = css`
  display: flex;
  flex-direction: row;
  align-items: center;
  padding-top: 8px;
`;

const STYLES_NAV = css`
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 58px;
  width: 100%;
  padding: 0 24px 0 24px;

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    padding: 0 16px 0 16px;
  }
`;

const STYLES_TITLE_TEXT = css`
  white-space: nowrap;
  padding: 0 0 0 8px;
  font-size: 1.3rem;
  display: flex;
  padding-bottom: 2px;
  font-family: ${Constants.fonts.demi};

  @media screen and (max-width: 400px) {
    display: none;
  }
`;

const STYLES_MENU_BUTTON = css`
  cursor: pointer;
  height: 100%;
  align-items: center;
  justify-content: center;
  padding-left: 24px;
  margin-left: 16px;
  border-left: 1px solid ${Constants.colors.border};
  text-decoration: none;
  color: ${Constants.colors.black};

  :visited {
    color: ${Constants.colors.black};
  }

  :hover {
    color: ${Constants.colors.expo};
  }

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    padding-left: 16px;
  }
`;

const STYLES_MENU_BUTTON_IS_MOBILE = css`
  display: none;

  @media screen and (max-width: ${Constants.breakpoints.mobile}) {
    display: flex;
  }
`;

const STYLES_MENU_BUTTON_VISIBLE = css`
  display: flex;
`;

const SECTION_LINK_CONTAINER = css`
  display: flex;
`;

const SECTION_LINK = css`
  text-decoration: none;
  font-weight: 900;
  font-family: expo-brand-demi, sans-serif;
  :hover {
    opacity: 0.5;
  }
`;

const SECTION_LINK_ACTIVE = css`
  text-decoration: underline;
`;

const SECTION_LINK_INACTIVE = css`
  color: #000 !important;
`;

function SectionContainer({ spaceBetween = 0, spaceAround = 0, children, style }) {
  return (

      {children.map((child, i) => (

          {child}

      ))}

  );
}

export default class DocumentationHeader extends React.PureComponent {
  render() {
    return (

            <Link href="/">

                <BrandLogo />

            </Link>

Expo

            <SectionContainer
              spaceBetween={15}
              style={{
                paddingLeft: 10,
                marginLeft: 15,
                borderLeftWidth: 1,
                borderLeftColor: '#eee',
                borderLeftStyle: 'solid',
              }}>
              <Link href="/">

                  Get Started

              </Link>
              <Link href="/guides">

                  Guides

              </Link>
              <Link href="/versions/latest/">

                  API Reference

              </Link>
            </SectionContainer>

          {!this.props.isAlogliaSearchHidden && (
            <AlgoliaSearch router={this.props.router} version={this.props.version} />
          )}

          {!this.props.isMenuActive && (
            <span
              className={`${STYLES_MENU_BUTTON} ${STYLES_MENU_BUTTON_IS_MOBILE}`}
              onClick={this.props.onShowMenu}>
              <MenuIcon />

          )}

          {this.props.isMenuActive && (
            <span
              className={`${STYLES_MENU_BUTTON} ${STYLES_MENU_BUTTON_VISIBLE}`}
              onClick={this.props.onHideMenu}>
              <DismissIcon />

          )}

    );
  }
}
<|endoftext|>


<commit_before>'use strict';

var path = require('path');
var util = require('util');
var async = require('async');
var _ = require('lodash');

var lpad = require('./lpad');

function Parallelizer(grunt, task) {
  this.grunt_ = grunt;
  this.task_ = task;
  this.cpCache_ = [];
}

Parallelizer.prototype.kill = function() {
  this.cpCache_.forEach(function(el) {
    el.kill();
  });
};

Parallelizer.prototype.exec = function(task, target) {
  var cb = this.task_.async();
  var splittedFilesSrc = this.getSplittedFilesSrc_(task, target);

  var spawnOptions;
  // Optionally log the task output
  // if (options.logConcurrentOutput) {
  //   spawnOptions = { stdio: 'inherit' };
  // }

  lpad('    ');
  var ok = true;
  async.forEach(splittedFilesSrc, function(filesSrc, next) {
    var filesOption = '--grunt-parallelize-child-filesSrc=' + filesSrc.join(path.delimiter);
    var cp = this.grunt_.util.spawn({
      grunt: true,
      args: [['parallelize', task, target].join(':')].concat(this.grunt_.option.flags(), filesOption),
      opts: spawnOptions
    }, function(err, result, code) {
      if ((err || code > 0)) {
        ok = false;
        if (result.stderr) {
          this.grunt_.warn(result.stderr);
        }
      }
      this.grunt_.log.write('\n' + this.filterOutput_(result.stdout, task, target) + '\n');
      next();
    }.bind(this));
    this.cpCache_.push(cp);
  }.bind(this), function() {
    lpad();
    if (!ok) {
      this.grunt_.log.writeln('');
    }
    cb(ok);
  }.bind(this));
};

Parallelizer.prototype.filterOutput_ = function(output, task, target) {
  var regex = new RegExp(util.format('^.*Running "parallelize:%s:%s".*\n\n', task, target), 'g');
  return output.replace(regex, '');
};

Parallelizer.prototype.getProcesses_ = function(task, target) {
  var processes = this.grunt_.config(['parallelize', task, target]);
  if (typeof processes === 'number') {
    return processes;
  } else if (processes) {
    processes = this.grunt_.config(['parallelize', task, 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
    processes = this.grunt_.config(['parallelize', 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
  }

  throw new Error('"processes" option not found');
};

Parallelizer.prototype.getSplittedFilesSrc_ = function(task, target) {
  var filesSrc = this.getNormalizedFilesSrc_(task, target);
  var processes = this.getProcesses_(task, target);
  if (processes < 0) {
    throw new Error('"processes" option shoud be positive');
  } else if (!processes) {
    return [];
  }
  var remain = filesSrc.length % processes;
  var per = (filesSrc.length - remain) / processes;
  var splittedFilesSrc = [];
  while (filesSrc.length) {
    splittedFilesSrc.push(filesSrc.splice(0, remain-- > 0 ? per + 1 : per));
  }
  return splittedFilesSrc;
};

Parallelizer.prototype.getNormalizedFilesSrc_ = function(task, target) {
  var configPath = [task, target];
  var config = this.grunt_.config(configPath);
  var files = this.grunt_.task.normalizeMultiTaskFiles(config);
  return _(files).chain().pluck('src').flatten().uniq().value();
};

module.exports = Parallelizer;
<commit_msg>Use var to point to 'this' to avoid binding in nested functions<commit_after>'use strict';

var path = require('path');
var util = require('util');
var async = require('async');
var _ = require('lodash');

var lpad = require('./lpad');

function Parallelizer(grunt, task) {
  this.grunt_ = grunt;
  this.task_ = task;
  this.cpCache_ = [];
}

Parallelizer.prototype.kill = function() {
  this.cpCache_.forEach(function(el) {
    el.kill();
  });
};

Parallelizer.prototype.exec = function(task, target) {
  var cb = this.task_.async();
  var splittedFilesSrc = this.getSplittedFilesSrc_(task, target);

  var spawnOptions;
  // Optionally log the task output
  // if (options.logConcurrentOutput) {
  //   spawnOptions = { stdio: 'inherit' };
  // }

  var self = this;
  lpad('    ');
  var ok = true;
  async.forEach(splittedFilesSrc, function(filesSrc, next) {
    var filesOption = '--grunt-parallelize-child-filesSrc=' + filesSrc.join(path.delimiter);
    var cp = self.grunt_.util.spawn({
      grunt: true,
      args: [['parallelize', task, target].join(':')].concat(self.grunt_.option.flags(), filesOption),
      opts: spawnOptions
    }, function(err, result, code) {
      if ((err || code > 0)) {
        ok = false;
        if (result.stderr) {
          self.grunt_.warn(result.stderr);
        }
      }
      self.grunt_.log.write('\n' + self.filterOutput_(result.stdout, task, target) + '\n');
      next();
    });
    self.cpCache_.push(cp);
  }, function() {
    lpad();
    if (!ok) {
      self.grunt_.log.writeln('');
    }
    cb(ok);
  });
};

Parallelizer.prototype.filterOutput_ = function(output, task, target) {
  var regex = new RegExp(util.format('^.*Running "parallelize:%s:%s".*\n\n', task, target), 'g');
  return output.replace(regex, '');
};

Parallelizer.prototype.getProcesses_ = function(task, target) {
  var processes = this.grunt_.config(['parallelize', task, target]);
  if (typeof processes === 'number') {
    return processes;
  } else if (processes) {
    processes = this.grunt_.config(['parallelize', task, 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
    processes = this.grunt_.config(['parallelize', 'options', 'processes']);
    if (typeof processes === 'number') {
      return processes;
    }
  }

  throw new Error('"processes" option not found');
};

Parallelizer.prototype.getSplittedFilesSrc_ = function(task, target) {
  var filesSrc = this.getNormalizedFilesSrc_(task, target);
  var processes = this.getProcesses_(task, target);
  if (processes < 0) {
    throw new Error('"processes" option shoud be positive');
  } else if (!processes) {
    return [];
  }
  var remain = filesSrc.length % processes;
  var per = (filesSrc.length - remain) / processes;
  var splittedFilesSrc = [];
  while (filesSrc.length) {
    splittedFilesSrc.push(filesSrc.splice(0, remain-- > 0 ? per + 1 : per));
  }
  return splittedFilesSrc;
};

Parallelizer.prototype.getNormalizedFilesSrc_ = function(task, target) {
  var configPath = [task, target];
  var config = this.grunt_.config(configPath);
  var files = this.grunt_.task.normalizeMultiTaskFiles(config);
  return _(files).chain().pluck('src').flatten().uniq().value();
};

module.exports = Parallelizer;
<|endoftext|>


<commit_before>const electron = require('electron');
const app = electron.app;
const Menu = electron.Menu;
const createMenuTemplate = require('./menutemplate');
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
const instagram = require('./instagram');
const autoUpdater = require('./autoupdater');
const client = require('electron-connect').client;

// fixes electron's timeout inconsistency
// not doing this on windows because the fix doesn't work for windows.
if (process.platform != 'win32') {
  require('./timeout-shim').fix();
}

const RATE_LIMIT_DELAY = 60000;
let pollingInterval = 10000;

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
let session;

function createWindow () {
  if (!mainWindow) {
    mainWindow = new BrowserWindow({
      width: 1200,
      height: 800,
      icon: `${__dirname}/../browser/img/icon.png`,
      minWidth: 500,
      minHeight: 400
    });
  }
  mainWindow.setTitle('IG:dm - Instagram Desktop Messenger');

  instagram.checkAuth(session).then((result) => {
    const view = result.isLoggedIn ? '../browser/index.html' : '../browser/login.html';
    session = result.session || session;

    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, view),
      protocol: 'file:',
      slashes: true
    }));
  });
  // If we're in development mode then create an Electron Connect client for live reload.
  if (process.defaultApp) {
    client.create(mainWindow);
  }
  mainWindow.on('closed', () => mainWindow = null);
}

function createOtpWindow (type) {
  const otpWindow = new BrowserWindow({
    width: 300,
    height: 300,
    resizable: false,
    icon: `${__dirname}/../browser/img/icon.png`,
  });
  otpWindow.setTitle('IG:dm - Instagram verification code');
  otpWindow.loadURL(url.format({
    pathname: path.join(__dirname, `../browser/${type}.html`),
    protocol: 'file:',
    slashes: true
  }));
  return otpWindow;
}

let chatListTimeoutObj;
function getChatList () {
  if (!session) {
    return;
  }
  instagram.getChatList(session).then((chats) => {
    mainWindow.webContents.send('chatList', chats);

    if (chatListTimeoutObj) {
      clearTimeout(chatListTimeoutObj);
    }
    chatListTimeoutObj = setTimeout(getChatList, pollingInterval);
  }).catch(() => setTimeout(getChatList, RATE_LIMIT_DELAY));
}

let chatTimeoutObj;
let messagesThread;
function getChat (evt, id) {
  if (!session) {
    return;
  }
  // used to get older messages, see #getOlderMessages
  if (messagesThread && messagesThread.threadId != id) {
    messagesThread = null;
  }

  instagram.getChat(session, id).then((chat) => {
    mainWindow.webContents.send('chat', chat);
    if (chatTimeoutObj) {
      clearTimeout(chatTimeoutObj);
    }
    chatTimeoutObj = setTimeout(getChat, pollingInterval, {}, id);
  }).catch(() => setTimeout(getChat, RATE_LIMIT_DELAY, evt, id));
}

function handleCheckpoint (checkpointError) {
  return new Promise((resolve, reject) => {
    instagram.startCheckpoint(checkpointError)
      .then((challenge) => {
        const cpWindow = createOtpWindow('checkpoint');
        electron.ipcMain.on('otpCode', (evt, data) => {
          electron.ipcMain.removeAllListeners('otpCode');
          cpWindow.close();
          challenge.code(data.code).then(resolve).catch(reject);
        });
      }).catch(reject);
  });
}

function handleTwoFactor (error) {
  return new Promise((resolve, reject) => {
    const tfWindow = createOtpWindow('twofactor');
    const username = error.json.two_factor_info.username;
    const twoFactorIdentifier = error.json.two_factor_info.two_factor_identifier;
    const trustThisDevice = '1';
    const verificationMethod = '1';
    electron.ipcMain.on('otpCode', (evt, data) =>{
      electron.ipcMain.removeAllListeners('otpCode');
      tfWindow.close();
      instagram.twoFactorLogin(
        username,
        data.code,
        twoFactorIdentifier,
        trustThisDevice,
        verificationMethod
      ).then(resolve).catch(reject);
    });
  });
}

// fixes this issue https://github.com/electron/electron/issues/10864
app.setAppUserModelId('com.ifedapoolarewaju.desktop.igdm');

app.on('ready', () => {
  createWindow();
  // only set the menu template when in production mode/
  // this also leaves the dev console enabled when in dev mode.
  if (!process.defaultApp) {
    const templatePromise = createMenuTemplate();
    templatePromise.then((template) => {
      const menu = Menu.buildFromTemplate(template);
      Menu.setApplicationMenu(menu);
    });
  }
  autoUpdater.init();
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  // only call createWindow after mainWindow is set to null at
  // mainWindow.on('closed')
  if (mainWindow === null) createWindow();
});

// reduce polling frequency when app is not active.
app.on('browser-window-blur', () => {
  pollingInterval = 30000;
});

app.on('browser-window-focus', () => {
  pollingInterval = 10000;
  app.setBadgeCount(0);
});

electron.ipcMain.on('login', (evt, data) => {
  if (data.username === '' || data.password === '') {
    return mainWindow.webContents.send('loginError', 'Please enter all required fields');
  }
  const login = (keepLastSession) => {
    instagram.login(data.username, data.password, keepLastSession).then((session_) => {
      session = session_;
      createWindow();
    }).catch((error) => {
      if (instagram.isCheckpointError(error)) {
        handleCheckpoint(error)
          .then(() => login(true))
          .catch(() => mainWindow.webContents.send('loginError', getErrorMsg(error)));
      } else if (instagram.isTwoFactorError(error)) {
        handleTwoFactor(error)
          .then(() => login(true))
          .catch((tferror) => mainWindow.webContents.send('loginError', getErrorMsg(tferror)));
      } else {
        mainWindow.webContents.send('loginError', getErrorMsg(error));
      }
    });
  };

  const getErrorMsg = (error) => {
    let message = 'An unknown error occurred.';
    if (error.message) {
      message = error.message;
    }
    return message;
  };

  login();
});

electron.ipcMain.on('logout', () => {
  instagram.logout();
  session = null;
  createWindow();
});

electron.ipcMain.on('getLoggedInUser', () => {
  instagram.getLoggedInUser(session).then((user) => {
    mainWindow.webContents.send('loggedInUser', user);
  });
});

electron.ipcMain.on('getChatList', getChatList);

electron.ipcMain.on('getChat', getChat);

electron.ipcMain.on('getOlderMessages', (_, id) => {
  instagram.getOlderMessages(session, messagesThread, id)
    .then((data) => {
      messagesThread = data.thread;
      mainWindow.webContents.send('olderMessages', {chatId: id, messages: data.messages});
    });
});

electron.ipcMain.on('message', (_, data) => {
  if (data.isNewChat) {
    instagram.sendNewChatMessage(session, data.message, data.users).then((chat) => {
      getChat(null, chat[0].id);
      getChatList();
    });
  } else {
    instagram.sendMessage(session, data.message, data.chatId).then(() => {
      getChat(null, data.chatId);
      getChatList();
    });
  }
});

electron.ipcMain.on('upload', (_, data) => {
  instagram.uploadFile(session, data.filePath, data.recipients)
    .then((chat) => getChat(null, chat.threads.thread_id))
    .catch(() => mainWindow.webContents.send('upload-error', data.chatId));
});

electron.ipcMain.on('searchUsers', (_, search) => {
  instagram.searchUsers(session, search).then((users) => {
    mainWindow.webContents.send('searchResult', users);
  });
});

electron.ipcMain.on('markAsRead', (_, thread) => {
  instagram.seen(session, thread);
});

electron.ipcMain.on('increase-badge-count', () => {
  app.setBadgeCount(app.getBadgeCount() + 1);
});

electron.ipcMain.on('getUnfollowers', () => {
  instagram.getUnfollowers(session).then((users) => {
    mainWindow.webContents.send('unfollowers', users);
  });
});

electron.ipcMain.on('unfollow', (_, userId) => {
  instagram.unfollow(session, userId);
});

electron.ipcMain.on('getDisplayPictureUrl', (_, userId) => {
  instagram.getUser(session, userId).then((user) => {
    mainWindow.webContents.send('getDisplayPictureUrl', { userId: userId, url: user._params.profilePicUrl });
  });
});
<commit_msg>SuggestedChanges<commit_after>const electron = require('electron');
const app = electron.app;
const Menu = electron.Menu;
const createMenuTemplate = require('./menutemplate');
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
const instagram = require('./instagram');
const autoUpdater = require('./autoupdater');
const client = require('electron-connect').client;

// fixes electron's timeout inconsistency
// not doing this on windows because the fix doesn't work for windows.
if (process.platform != 'win32') {
  require('./timeout-shim').fix();
}

const RATE_LIMIT_DELAY = 60000;
let pollingInterval = 10000;

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
let session;

function createWindow () {
  if (!mainWindow) {
    mainWindow = new BrowserWindow({
      width: 1200,
      height: 800,
      icon: `${__dirname}/../browser/img/icon.png`,
      minWidth: 500,
      minHeight: 400
    });
  }
  mainWindow.setTitle('IG:dm - Instagram Desktop Messenger');

  instagram.checkAuth(session).then((result) => {
    const view = result.isLoggedIn ? '../browser/index.html' : '../browser/login.html';
    session = result.session || session;

    mainWindow.loadURL(url.format({
      pathname: path.join(__dirname, view),
      protocol: 'file:',
      slashes: true
    }));
  });
  // If we're in development mode then create an Electron Connect client for live reload.
  if (process.defaultApp) {
    client.create(mainWindow);
  }
  mainWindow.on('closed', () => mainWindow = null);
}

function createOtpWindow (type) {
  const otpWindow = new BrowserWindow({
    width: 300,
    height: 300,
    resizable: false,
    icon: `${__dirname}/../browser/img/icon.png`,
  });
  otpWindow.setTitle('IG:dm - Instagram verification code');
  otpWindow.loadURL(url.format({
    pathname: path.join(__dirname, `../browser/${type}.html`),
    protocol: 'file:',
    slashes: true
  }));
  return otpWindow;
}

let chatListTimeoutObj;
function getChatList () {
  if (!session) {
    return;
  }
  instagram.getChatList(session).then((chats) => {
    mainWindow.webContents.send('chatList', chats);

    if (chatListTimeoutObj) {
      clearTimeout(chatListTimeoutObj);
    }
    chatListTimeoutObj = setTimeout(getChatList, pollingInterval);
  }).catch(() => setTimeout(getChatList, RATE_LIMIT_DELAY));
}

let chatTimeoutObj;
let messagesThread;
function getChat (evt, id) {
  if (!session) {
    return;
  }
  // used to get older messages, see #getOlderMessages
  if (messagesThread && messagesThread.threadId != id) {
    messagesThread = null;
  }

  instagram.getChat(session, id).then((chat) => {
    mainWindow.webContents.send('chat', chat);
    if (chatTimeoutObj) {
      clearTimeout(chatTimeoutObj);
    }
    chatTimeoutObj = setTimeout(getChat, pollingInterval, {}, id);
  }).catch(() => setTimeout(getChat, RATE_LIMIT_DELAY, evt, id));
}

function handleCheckpoint (checkpointError) {
  return new Promise((resolve, reject) => {
    instagram.startCheckpoint(checkpointError)
      .then((challenge) => {
        const cpWindow = createOtpWindow('checkpoint');
        electron.ipcMain.on('otpCode', (evt, data) => {
          electron.ipcMain.removeAllListeners('otpCode');
          cpWindow.close();
          challenge.code(data.code).then(resolve).catch(reject);
        });
      }).catch(reject);
  });
}

function handleTwoFactor (error) {
  return new Promise((resolve, reject) => {
    const tfWindow = createOtpWindow('twofactor');
    const username = error.json.two_factor_info.username;
    const twoFactorIdentifier = error.json.two_factor_info.two_factor_identifier;
    const trustThisDevice = '1';
    const verificationMethod = '1';
    electron.ipcMain.on('otpCode', (evt, data) =>{
      electron.ipcMain.removeAllListeners('otpCode');
      tfWindow.close();
      instagram.twoFactorLogin(
        username,
        data.code,
        twoFactorIdentifier,
        trustThisDevice,
        verificationMethod
      ).then(resolve).catch(reject);
    });
  });
}

// fixes this issue https://github.com/electron/electron/issues/10864
app.setAppUserModelId('com.ifedapoolarewaju.desktop.igdm');

app.on('ready', () => {
  createWindow();
  // only set the menu template when in production mode/
  // this also leaves the dev console enabled when in dev mode.
  if (!process.defaultApp) {
    createMenuTemplate().then((template) => {
      const menu = Menu.buildFromTemplate(template);
      Menu.setApplicationMenu(menu);
    });
  }
  autoUpdater.init();
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') app.quit();
});

app.on('activate', () => {
  // On OS X it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  // only call createWindow after mainWindow is set to null at
  // mainWindow.on('closed')
  if (mainWindow === null) createWindow();
});

// reduce polling frequency when app is not active.
app.on('browser-window-blur', () => {
  pollingInterval = 30000;
});

app.on('browser-window-focus', () => {
  pollingInterval = 10000;
  app.setBadgeCount(0);
});

electron.ipcMain.on('login', (evt, data) => {
  if (data.username === '' || data.password === '') {
    return mainWindow.webContents.send('loginError', 'Please enter all required fields');
  }
  const login = (keepLastSession) => {
    instagram.login(data.username, data.password, keepLastSession).then((session_) => {
      session = session_;
      createWindow();
    }).catch((error) => {
      if (instagram.isCheckpointError(error)) {
        handleCheckpoint(error)
          .then(() => login(true))
          .catch(() => mainWindow.webContents.send('loginError', getErrorMsg(error)));
      } else if (instagram.isTwoFactorError(error)) {
        handleTwoFactor(error)
          .then(() => login(true))
          .catch((tferror) => mainWindow.webContents.send('loginError', getErrorMsg(tferror)));
      } else {
        mainWindow.webContents.send('loginError', getErrorMsg(error));
      }
    });
  };

  const getErrorMsg = (error) => {
    let message = 'An unknown error occurred.';
    if (error.message) {
      message = error.message;
    }
    return message;
  };

  login();
});

electron.ipcMain.on('logout', () => {
  instagram.logout();
  session = null;
  createWindow();
});

electron.ipcMain.on('getLoggedInUser', () => {
  instagram.getLoggedInUser(session).then((user) => {
    mainWindow.webContents.send('loggedInUser', user);
  });
});

electron.ipcMain.on('getChatList', getChatList);

electron.ipcMain.on('getChat', getChat);

electron.ipcMain.on('getOlderMessages', (_, id) => {
  instagram.getOlderMessages(session, messagesThread, id)
    .then((data) => {
      messagesThread = data.thread;
      mainWindow.webContents.send('olderMessages', {chatId: id, messages: data.messages});
    });
});

electron.ipcMain.on('message', (_, data) => {
  if (data.isNewChat) {
    instagram.sendNewChatMessage(session, data.message, data.users).then((chat) => {
      getChat(null, chat[0].id);
      getChatList();
    });
  } else {
    instagram.sendMessage(session, data.message, data.chatId).then(() => {
      getChat(null, data.chatId);
      getChatList();
    });
  }
});

electron.ipcMain.on('upload', (_, data) => {
  instagram.uploadFile(session, data.filePath, data.recipients)
    .then((chat) => getChat(null, chat.threads.thread_id))
    .catch(() => mainWindow.webContents.send('upload-error', data.chatId));
});

electron.ipcMain.on('searchUsers', (_, search) => {
  instagram.searchUsers(session, search).then((users) => {
    mainWindow.webContents.send('searchResult', users);
  });
});

electron.ipcMain.on('markAsRead', (_, thread) => {
  instagram.seen(session, thread);
});

electron.ipcMain.on('increase-badge-count', () => {
  app.setBadgeCount(app.getBadgeCount() + 1);
});

electron.ipcMain.on('getUnfollowers', () => {
  instagram.getUnfollowers(session).then((users) => {
    mainWindow.webContents.send('unfollowers', users);
  });
});

electron.ipcMain.on('unfollow', (_, userId) => {
  instagram.unfollow(session, userId);
});

electron.ipcMain.on('getDisplayPictureUrl', (_, userId) => {
  instagram.getUser(session, userId).then((user) => {
    mainWindow.webContents.send('getDisplayPictureUrl', { userId: userId, url: user._params.profilePicUrl });
  });
});
<|endoftext|>


<commit_before>'use strict';

class PixelChange {

    static compareGrayPixels(diff, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i++) {
            if(Math.abs(buf0[i] - buf1[i]) >= diff) {diffs++;}
        }
        return Math.floor(100 * diffs / wxh);
    }

    static compareRgbPixels(diff, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i+=3) {
            if(Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}
        }
        return Math.floor(100 * diffs / wxh);
    }

    static compareRgbaPixels(diff, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i+=4) {
            if(Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}
        }
        return Math.floor(100 * diffs / wxh);
    }

    static compareGrayRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let p = 0; p < bufLen; p++) {
            const diff = Math.abs(buf0[p] - buf1[p]);
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            results.push({name: regions[i].name, percent: Math.floor(100 * diffs[i] / regions[i].count)});
        }
        return results;
    }

    static compareRgbRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let i = 0, p = 0; i < bufLen; i+=3, p++) {
            const diff = Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3;
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            results.push({name: regions[i].name, percent: Math.floor(100 * diffs[i] / regions[i].count)});
        }
        return results;
    }

    static compareRgbaRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let i = 0, p = 0; i < bufLen; i+=4, p++) {
            const diff = Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3;
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            results.push({name: regions[i].name, percent: Math.floor(100 * diffs[i] / regions[i].count)});
        }
        return results;
    }
}

module.exports = PixelChange;

//todo - should always return array
//todo - array will only be populated when percent >= percent
//todo - percent will have to be passed into method
//todo - will have to test this behavior on n-api module first to keep symmetry
//todo(ne) - check integrity of data before sending here to be processed<commit_msg>pass percents and return arrays for all methods<commit_after>'use strict';

class PixelChange {

    static compareGrayPixels(diff, percent, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i++) {if(Math.abs(buf0[i] - buf1[i]) >= diff) {diffs++;}}
        const perc = Math.floor(100 * diffs / wxh);
        if (perc >= percent) {return [{name: "percent", percent: perc}];}
        return [];
    }

    static compareRgbPixels(diff, percent, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i+=3) {if(Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}}
        const perc = Math.floor(100 * diffs / wxh);
        if (perc >= percent) {return [{name: "percent", percent: perc}];}
        return [];
    }

    static compareRgbaPixels(diff, percent, wxh, bufLen, buf0, buf1) {
        let diffs = 0;
        for (let i = 0; i < bufLen; i+=4) {if(Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3 >= diff) {diffs++;}}
        const perc = Math.floor(100 * diffs / wxh);
        if (perc >= percent) {return [{name: "percent", percent: perc}];}
        return [];
    }

    static compareGrayRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let p = 0; p < bufLen; p++) {
            const diff = Math.abs(buf0[p] - buf1[p]);
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            const percent = Math.floor(100 * diffs[i] / regions[i].count);
            if (regions[i].percent > percent) {continue;}
            results.push({name: regions[i].name, percent: percent});
        }
        return results;
    }

    static compareRgbRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let i = 0, p = 0; i < bufLen; i+=3, p++) {
            const diff = Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3;
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            const percent = Math.floor(100 * diffs[i] / regions[i].count);
            if (regions[i].percent > percent) {continue;}
            results.push({name: regions[i].name, percent: percent});
        }
        return results;
    }

    static compareRgbaRegions(minDiff, regLen, regions, bufLen, buf0, buf1) {
        const diffs = new Uint32Array(regLen);
        for (let i = 0, p = 0; i < bufLen; i+=4, p++) {
            const diff = Math.abs(buf0[i] + buf0[i+1] + buf0[i+2] - buf1[i] - buf1[i+1] - buf1[i+2])/3;
            if (minDiff > diff) {continue;}
            for (let i = 0; i < regLen; i++) {
                const region = regions[i];
                if (!region.bitset[p] || diff < region.diff) {continue;}
                diffs[i]++;
            }
        }
        const results = [];
        for (let i = 0; i < regLen; i++) {
            const percent = Math.floor(100 * diffs[i] / regions[i].count);
            if (regions[i].percent > percent) {continue;}
            results.push({name: regions[i].name, percent: percent});
        }
        return results;
    }
}

module.exports = PixelChange;

//todo(ne) - should always return array
//todo(ne) - array will only be populated when percent >= percent
//todo(ne) - percent will have to be passed into method
//todo - will have to test this behavior on n-api module first to maintain symmetry
//todo(ne) - check integrity of data before sending here to be processed<|endoftext|>


<commit_before>"use babel";

import Backbone from "backbone";
import "leaflet";
import {allowUnsafeNewFunction} from "loophole";
import {$, View} from "space-pen";

import "../vendor/cartodb.js/jscrollpane";
import "../vendor/cartodb.js/spin";
import "../vendor/cartodb.js/lzma";
import "../vendor/cartodb.js/html-css-sanitizer-bundle";

import "../vendor/cartodb.js/cartodb";

import "../vendor/cartodb.js/core/config";
import "../vendor/cartodb.js/core/loader";
import "../vendor/cartodb.js/core/log";
import "../vendor/cartodb.js/core/model";
import "../vendor/cartodb.js/core/profiler";
import "../vendor/cartodb.js/core/sanitize";
import "../vendor/cartodb.js/core/template";
import "../vendor/cartodb.js/core/util";
import "../vendor/cartodb.js/core/view";

import "../vendor/cartodb.js/geo/ui/text";
import "../vendor/cartodb.js/geo/ui/annotation";
import "../vendor/cartodb.js/geo/ui/image";
import "../vendor/cartodb.js/geo/ui/share";
import "../vendor/cartodb.js/geo/ui/zoom";
import "../vendor/cartodb.js/geo/ui/zoom_info";
// uses underscore templating
//   see https://discuss.atom.io/t/--template-causes-unsafe-eval-error/9310
allowUnsafeNewFunction(() => require("../vendor/cartodb.js/geo/ui/legend"));
// import "../vendor/cartodb.js/geo/ui/legend";
import "../vendor/cartodb.js/geo/ui/switcher";
import "../vendor/cartodb.js/geo/ui/infowindow";
import "../vendor/cartodb.js/geo/ui/header";
import "../vendor/cartodb.js/geo/ui/search";
import "../vendor/cartodb.js/geo/ui/layer_selector";
import "../vendor/cartodb.js/geo/ui/slides_controller";
import "../vendor/cartodb.js/geo/ui/mobile";
import "../vendor/cartodb.js/geo/ui/tiles_loader";
import "../vendor/cartodb.js/geo/ui/infobox";
import "../vendor/cartodb.js/geo/ui/tooltip";
import "../vendor/cartodb.js/geo/ui/fullscreen";

import "../vendor/cartodb.js/geo/common";
import "../vendor/cartodb.js/geo/layer_definition";
import "../vendor/cartodb.js/geo/geometry";
import "../vendor/cartodb.js/geo/map";
import "../vendor/cartodb.js/geo/sublayer";

import "../vendor/cartodb.js/geo/leaflet/leaflet_base";
import "../vendor/cartodb.js/geo/leaflet/leaflet_tiledlayer";
import "../vendor/cartodb.js/geo/leaflet/leaflet_cartodb_layergroup";
import "../vendor/cartodb.js/geo/leaflet/leaflet_cartodb_layer";
import "../vendor/cartodb.js/geo/leaflet/leaflet";

import "../vendor/cartodb.js/vis/vis";
import "../vendor/cartodb.js/vis/layers";
import "../vendor/cartodb.js/vis/overlays";

import "../vendor/cartodb.js/api/layers";
import "../vendor/cartodb.js/api/vis";

Backbone.setDomLibrary($);

// TODO MapView
// see https://github.com/atom/space-pen for documentation
export default class PreviewView extends View {
  static content() {
    return this.div({
      class: "cartodb-preview native-key-bindings",
      tabindex: -1
    });
  }

  static deserialize(state) {
    return new PreviewView(state);
  }

  constructor(...args) {
    super(...args);
  }

  attached() {
    console.log("attached");
    /*
    this.map = L.map($(this.html).find(".cartodb-preview")[0], {
      center: [0, 0],
      // scrollWheelZoom: false,
      zoom: 4
    });

    this.map.attributionControl.setPrefix('');

    // L.tileLayer("http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png", {
    //   attribution: '© OpenStreetMap contributors, © CartoDB'
    // }).addTo(this.map);

    cartodb
      .createLayer(this.map, "http://documentation.cartodb.com/api/v2/viz/2b13c956-e7c1-11e2-806b-5404a6a683d5/viz.json")
      .addTo(this.map);
    */

    cartodb.createVis($(this.html).find(".cartodb-preview")[0], "http://documentation.cartodb.com/api/v2/viz/2b13c956-e7c1-11e2-806b-5404a6a683d5/viz.json");
  }

  detached() {
    console.log("detached");
    this.map.remove();
  }

  serialize() {
    return {
      deserializer: "PreviewView"
    }
  }

  getTitle() {
    return "Preview";
  }

  getURI() {
    console.log("getURI");
    return "cartodb://preview/";
  }
};

atom.deserializers.add(PreviewView);
<commit_msg>A visualization that triggers errors<commit_after>"use babel";

import Backbone from "backbone";
import "leaflet";
import {allowUnsafeNewFunction} from "loophole";
import {$, View} from "space-pen";

import "../vendor/cartodb.js/jscrollpane";
import "../vendor/cartodb.js/spin";
import "../vendor/cartodb.js/lzma";
import "../vendor/cartodb.js/html-css-sanitizer-bundle";

import "../vendor/cartodb.js/cartodb";

import "../vendor/cartodb.js/core/config";
import "../vendor/cartodb.js/core/loader";
import "../vendor/cartodb.js/core/log";
import "../vendor/cartodb.js/core/model";
import "../vendor/cartodb.js/core/profiler";
import "../vendor/cartodb.js/core/sanitize";
import "../vendor/cartodb.js/core/template";
import "../vendor/cartodb.js/core/util";
import "../vendor/cartodb.js/core/view";

import "../vendor/cartodb.js/geo/ui/text";
import "../vendor/cartodb.js/geo/ui/annotation";
import "../vendor/cartodb.js/geo/ui/image";
import "../vendor/cartodb.js/geo/ui/share";
import "../vendor/cartodb.js/geo/ui/zoom";
import "../vendor/cartodb.js/geo/ui/zoom_info";
// uses underscore templating
//   see https://discuss.atom.io/t/--template-causes-unsafe-eval-error/9310
allowUnsafeNewFunction(() => require("../vendor/cartodb.js/geo/ui/legend"));
// import "../vendor/cartodb.js/geo/ui/legend";
import "../vendor/cartodb.js/geo/ui/switcher";
import "../vendor/cartodb.js/geo/ui/infowindow";
import "../vendor/cartodb.js/geo/ui/header";
import "../vendor/cartodb.js/geo/ui/search";
import "../vendor/cartodb.js/geo/ui/layer_selector";
import "../vendor/cartodb.js/geo/ui/slides_controller";
import "../vendor/cartodb.js/geo/ui/mobile";
import "../vendor/cartodb.js/geo/ui/tiles_loader";
import "../vendor/cartodb.js/geo/ui/infobox";
import "../vendor/cartodb.js/geo/ui/tooltip";
import "../vendor/cartodb.js/geo/ui/fullscreen";

import "../vendor/cartodb.js/geo/common";
import "../vendor/cartodb.js/geo/layer_definition";
import "../vendor/cartodb.js/geo/geometry";
import "../vendor/cartodb.js/geo/map";
import "../vendor/cartodb.js/geo/sublayer";

import "../vendor/cartodb.js/geo/leaflet/leaflet_base";
import "../vendor/cartodb.js/geo/leaflet/leaflet_tiledlayer";
import "../vendor/cartodb.js/geo/leaflet/leaflet_cartodb_layergroup";
import "../vendor/cartodb.js/geo/leaflet/leaflet_cartodb_layer";
import "../vendor/cartodb.js/geo/leaflet/leaflet";

import "../vendor/cartodb.js/vis/vis";
import "../vendor/cartodb.js/vis/layers";
import "../vendor/cartodb.js/vis/overlays";

import "../vendor/cartodb.js/api/layers";
import "../vendor/cartodb.js/api/vis";

Backbone.setDomLibrary($);

// TODO MapView
// see https://github.com/atom/space-pen for documentation
export default class PreviewView extends View {
  static content() {
    return this.div({
      class: "cartodb-preview native-key-bindings",
      tabindex: -1
    });
  }

  static deserialize(state) {
    return new PreviewView(state);
  }

  constructor(...args) {
    super(...args);
  }

  attached() {
    console.log("attached");
    /*
    this.map = L.map($(this.html).find(".cartodb-preview")[0], {
      center: [0, 0],
      // scrollWheelZoom: false,
      zoom: 4
    });

    this.map.attributionControl.setPrefix('');

    // L.tileLayer("http://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}.png", {
    //   attribution: '© OpenStreetMap contributors, © CartoDB'
    // }).addTo(this.map);

    cartodb
      .createLayer(this.map, "http://documentation.cartodb.com/api/v2/viz/2b13c956-e7c1-11e2-806b-5404a6a683d5/viz.json")
      .addTo(this.map);
    */

    // cartodb.createVis($(this.html).find(".cartodb-preview")[0], "http://documentation.cartodb.com/api/v2/viz/2b13c956-e7c1-11e2-806b-5404a6a683d5/viz.json");
    cartodb.createVis($(this.html).find(".cartodb-preview")[0], "http://wnstnsmth.cartodb.com/api/v2/viz/649eafa8-0901-11e4-99f0-0e10bcd91c2b/viz.json");
  }

  detached() {
    console.log("detached");
    this.map.remove();
  }

  serialize() {
    return {
      deserializer: "PreviewView"
    }
  }

  getTitle() {
    return "Preview";
  }

  getURI() {
    console.log("getURI");
    return "cartodb://preview/";
  }
};

atom.deserializers.add(PreviewView);
<|endoftext|>


<commit_before>"use strict";

/*
 * This module handles the logic of processing a single
 * given file, whether it is a template, page or partial.
 *
 * The compiler, options, readers and file matchers to
 * be used are all injected.
 *
 * Mainly, this module makes sure that circular dependencies
 * do not occur with partial inclusions, by keeping track
 * of processed files.
 */

module.exports = setup;

var _ = require("underscore");

function setup (config) {

  var options            = config.options || {},
      read_header        = config.read_header,
      compile            = config.compile,
      find_closest_match = config.find_closest_match;

  var process_page    = process_file.bind(null, '.'),
      process_partial = process_file.bind(null, options.partials),
      processed       = {};

  var initial_template_params = _.extend({}, options.vars, { include: process_partial });

  return process_page;

  function process_file (folder, filename, params) {
    var input_file = find_closest_match(folder, filename);

    if (processed[input_file]) throw new Error("Circular dependency detected.");

    processed[input_file] = true;

    var compiled_page = page(input_file, params);

    delete processed[input_file];

    return compiled_page;
  };

  function page (input_file, params) {
    var header = read_header(input_file);
    var content = compile(input_file, bundle_template_params(header, params));
    return bundle_page(content, header);
  }

  function bundle_template_params () {
    return _.flatten([
      initial_template_params,
      arguments
    ]).reduce(function (agg, value) {
      return _.extend(agg, value);
    }, {});
  }

  function bundle_page (str, parameters) {
    return _.extend(parameters, {
      valueOf:  function () { return str; },
      toString: function () { return str; }
    });
  }
}
<commit_msg>Make basic template spec pass<commit_after>"use strict";

/*
 * This module handles the logic of processing a single
 * given file, whether it is a template, page or partial.
 *
 * The compiler, options, readers and file matchers to
 * be used are all injected.
 *
 * Mainly, this module makes sure that circular dependencies
 * do not occur with partial inclusions, by keeping track
 * of processed files.
 */

module.exports = setup;

var _ = require("underscore");

function setup (config) {

  var options            = config.options || {},
      read_header        = config.read_header,
      compile            = config.compile,
      find_closest_match = config.find_closest_match;

  var process_page     = process_file.bind(null, "."),
      process_partial  = process_file.bind(null, options.partials),
      process_template = process_file.bind(null, options.templates),
      processed        = {};

  var initial_template_params = _.extend({}, options.vars, { include: process_partial });

  return process_page;

  function process_file (folder, filename, params) {
    console.log("Now processing " + filename);
    var input_file = find_closest_match(folder, filename);

    if (processed[input_file]) throw new Error("Circular dependency detected.");

    processed[input_file] = true;

    var compiled_page = page(input_file, params);

    delete processed[input_file];

    return compiled_page;
  };

  function page (input_file, params) {
    console.log("Paging " + input_file);
    var header = read_header(input_file);
    console.log("Header was " + JSON.stringify(header));
    var content = compile(input_file, bundle_template_params(header, params));

    if (header.template) {
      console.log("The page had a header; inject")
      var compiled_page = content;
      content = process_template(header.template,
                                 {document: compiled_page}).toString();
    }

    return bundle_page(content, header);
  }

  function bundle_template_params () {
    return _.flatten([
      initial_template_params,
      arguments
    ]).reduce(function (agg, value) {
      return _.extend(agg, value);
    }, {});
  }

  function bundle_page (str, parameters) {
    return _.extend(parameters, {
      valueOf:  function () { return str; },
      toString: function () { return str; }
    });
  }
}
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var conn = require('../common/connection.js'),
    util = require('../common/util.js');

var PUBSUB_BASE_URL = 'https://www.googleapis.com/pubsub/v1beta1',
    SCOPES = [
      'https://www.googleapis.com/auth/pubsub',
      'https://www.googleapis.com/auth/cloud-platform'
    ];

function Subscription(conn, name) {
  this.conn = conn;
  this.name = name;
}

Subscription.prototype.ack = function(ids, callback) {
  ids = util.arrayize(ids);
  var body = {
    subscription: this.name,
    ackId: ids
  };
  this.conn.makeReq('POST', 'subscriptions/acknowledge', null, body, callback);
};

Subscription.prototype.pull = function(opts, callback) {
  // TODO(jbd): Make opts optional.
  var body = {
    subscription: this.name,
    returnImmediately: !!opts.returnImmediately
  };
  this.conn.makeReq('POST', 'subscriptions/pull', null, body, callback);
};

Subscription.prototype.unsubscribe = function(opt_callback) {
  cb = opt_callback || util.noop;
  var path = util.format('subscriptions/{fullName}', {
    fullName: this.name
  });
  this.conn.makeReq('DELETE', path, null, true, cb);
};

Subscription.prototype.modify = function(opts, callback) {
  throw new Error('not yet implemented');
};

function Topic(conn, name) {
  this.conn = conn;
  this.name = name;
}

Topic.prototype.publish = function(data, opt_callback) {
  cb = opt_callback || util.noop;
  var body = {
    topic: this.name,
    data: data
  };
  this.conn.makeReq('POST', 'topics/publish', null, body, cb);
};

Topic.prototype.publishRaw = function(message, opt_callback) {
  cb = opt_callback || util.noop;
  message.topic = this.name;
  this.conn.makeReq('POST', 'topics/publish', null, body, cb);
};

Topic.prototype.del = function(opt_callback) {
   this.conn.makeReq('DELETE', this.name, null, true, cb);
};

// TODO(jbd): List subscriptions.

Topic.prototype.subscribe = function(opts, opt_callback) {
  var conn = this.conn;
  cb = opt_callback || util.noop;
  var body = {
    topic: this.name,
    name: '/subscriptions/' + conn.id + '/' + opts.name,
    ackDeadlineSeconds: opts.ackDeadlineSeconds
  };
  this.conn.makeReq('POST', 'subscriptions', null, body, function(err, item) {
    if (!err || (err && err.code == 409)) {
      cb(null, new Subscription(conn, body.name));
      return;
    }
    cb(err);
  });
};

function Connection(opts) {
  opts = opts || {};
  var id = opts.projectId;

  this.id = id;
  this.conn = new conn.Connection({
    email: opts.email,
    privateKey: opts.pemFilePath,
    scopes: SCOPES
  });
}

// TODO(jbd): Add listTopics.

Connection.prototype.createTopic = function(name, opt_callback) {
  var that = this;
  cb = opt_callback || util.noop;
  var fullName = util.format('/topics/{projectId}/{name}', {
    projectId: this.id,
    name: name
  });
  var body = { name: fullName };
  this.makeReq('POST', 'topics', null, body, function(err) {
    // TOOD(jbd): 409 doesn't necessarily mean
    // topic already exists. Check the error cause.
    if (!err || (err && err.code == 409)) {
      cb(null, new Topic(that, fullName));
      return;
    }
    cb(err);
  });
};

// TOOD(jbd): Don't duplicate, unify this with bucket.makeReq.
Connection.prototype.makeReq = function(method, path, q, body, callback) {
  var reqOpts = {
    method: method,
    qs: q,
    uri: util.format('{base}/{path}', {
      base: PUBSUB_BASE_URL,
      path: path
    })
  };
  if (body) {
    reqOpts.json = body;
  }
  this.conn.req(reqOpts, function(err, res, body) {
    if (body && body.error) {
      return callback(body.error);
    }
    if (res && (res.statusCode < 200 || res.statusCode > 299)) {
      return callback(new Error('error during request, statusCode: ' + res.statusCode));
    }
    callback(err, body);
  });
};

/**
 * Exports Connection.
 */
module.exports.Connection = Connection;
<commit_msg>pubsub: Rename publishRaw to publishMessage.<commit_after>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

var conn = require('../common/connection.js'),
    util = require('../common/util.js');

var PUBSUB_BASE_URL = 'https://www.googleapis.com/pubsub/v1beta1',
    SCOPES = [
      'https://www.googleapis.com/auth/pubsub',
      'https://www.googleapis.com/auth/cloud-platform'
    ];

function Subscription(conn, name) {
  this.conn = conn;
  this.name = name;
}

Subscription.prototype.ack = function(ids, callback) {
  ids = util.arrayize(ids);
  var body = {
    subscription: this.name,
    ackId: ids
  };
  this.conn.makeReq('POST', 'subscriptions/acknowledge', null, body, callback);
};

Subscription.prototype.pull = function(opts, callback) {
  // TODO(jbd): Make opts optional.
  var body = {
    subscription: this.name,
    returnImmediately: !!opts.returnImmediately
  };
  this.conn.makeReq('POST', 'subscriptions/pull', null, body, callback);
};

Subscription.prototype.unsubscribe = function(opt_callback) {
  cb = opt_callback || util.noop;
  var path = util.format('subscriptions/{fullName}', {
    fullName: this.name
  });
  this.conn.makeReq('DELETE', path, null, true, cb);
};

Subscription.prototype.modify = function(opts, callback) {
  throw new Error('not yet implemented');
};

function Topic(conn, name) {
  this.conn = conn;
  this.name = name;
}

Topic.prototype.publish = function(data, opt_callback) {
  this.publishMessage({ topic: this.name, data: data }, opt_callback);
};

Topic.prototype.publishMessage = function(message, opt_callback) {
  cb = opt_callback || util.noop;
  message.topic = this.name;
  this.conn.makeReq('POST', 'topics/publish', null, body, cb);
};

Topic.prototype.del = function(opt_callback) {
   this.conn.makeReq('DELETE', this.name, null, true, cb);
};

// TODO(jbd): List subscriptions.

Topic.prototype.subscribe = function(opts, opt_callback) {
  var conn = this.conn;
  cb = opt_callback || util.noop;
  var body = {
    topic: this.name,
    name: '/subscriptions/' + conn.id + '/' + opts.name,
    ackDeadlineSeconds: opts.ackDeadlineSeconds
  };
  this.conn.makeReq('POST', 'subscriptions', null, body, function(err, item) {
    if (!err || (err && err.code == 409)) {
      cb(null, new Subscription(conn, body.name));
      return;
    }
    cb(err);
  });
};

function Connection(opts) {
  opts = opts || {};
  var id = opts.projectId;

  this.id = id;
  this.conn = new conn.Connection({
    email: opts.email,
    privateKey: opts.pemFilePath,
    scopes: SCOPES
  });
}

// TODO(jbd): Add listTopics.

Connection.prototype.createTopic = function(name, opt_callback) {
  var that = this;
  cb = opt_callback || util.noop;
  var fullName = util.format('/topics/{projectId}/{name}', {
    projectId: this.id,
    name: name
  });
  var body = { name: fullName };
  this.makeReq('POST', 'topics', null, body, function(err) {
    // TOOD(jbd): 409 doesn't necessarily mean
    // topic already exists. Check the error cause.
    if (!err || (err && err.code == 409)) {
      cb(null, new Topic(that, fullName));
      return;
    }
    cb(err);
  });
};

// TOOD(jbd): Don't duplicate, unify this with bucket.makeReq.
Connection.prototype.makeReq = function(method, path, q, body, callback) {
  var reqOpts = {
    method: method,
    qs: q,
    uri: util.format('{base}/{path}', {
      base: PUBSUB_BASE_URL,
      path: path
    })
  };
  if (body) {
    reqOpts.json = body;
  }
  this.conn.req(reqOpts, function(err, res, body) {
    if (body && body.error) {
      return callback(body.error);
    }
    if (res && (res.statusCode < 200 || res.statusCode > 299)) {
      return callback(new Error('error during request, statusCode: ' + res.statusCode));
    }
    callback(err, body);
  });
};

/**
 * Exports Connection.
 */
module.exports.Connection = Connection;
<|endoftext|>