Skip to content
This repository has been archived by the owner on Sep 6, 2021. It is now read-only.

Contributors List on the About Dialog #2934

Merged
merged 12 commits into from
Mar 1, 2013
3 changes: 2 additions & 1 deletion src/brackets.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"report_issue_url" : "https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue",
"twitter_url" : "https://twitter.com/brackets",
"troubleshoot_url" : "https://github.com/adobe/brackets/wiki/Troubleshooting#wiki-livedev",
"twitter_name" : "@brackets"
"twitter_name" : "@brackets",
"contributors_url" : "https://api.github.com/repos/adobe/brackets/contributors"
}
}
3 changes: 2 additions & 1 deletion src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
"report_issue_url": "https://github.com/adobe/brackets/wiki/How-to-Report-an-Issue",
"twitter_url": "https://twitter.com/brackets",
"troubleshoot_url": "https://github.com/adobe/brackets/wiki/Troubleshooting#wiki-livedev",
"twitter_name": "@brackets"
"twitter_name": "@brackets",
"contributors_url": "https://api.github.com/repos/adobe/brackets/contributors"
},
"name": "Brackets",
"version": "0.21.0-0",
Expand Down
100 changes: 97 additions & 3 deletions src/help/HelpCommandHandlers.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@


/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
/*global define, $, brackets, window, Mustache */
/*global define, $, brackets, window, PathUtils, Mustache */

define(function (require, exports, module) {
"use strict";
Expand All @@ -38,11 +38,73 @@ define(function (require, exports, module) {
UpdateNotification = require("utils/UpdateNotification"),
FileUtils = require("file/FileUtils"),
NativeApp = require("utils/NativeApp"),
PreferencesManager = require("preferences/PreferencesManager"),
StringUtils = require("utils/StringUtils"),
AboutDialogTemplate = require("text!htmlContent/about-dialog.html");
AboutDialogTemplate = require("text!htmlContent/about-dialog.html"),
ContributorsTemplate = require("text!htmlContent/contributors-list.html");

var buildInfo;


// PreferenceStorage
var _prefs = PreferencesManager.getPreferenceStorage(module.id);

// Last time the contributorsInfo was fetched
var _lastContributorsFetchTime = _prefs.getValue("lastContributorsFetchTime");


/**
* @private
* Gets a data structure that has the information for all the contributors of Brackets.
* The information is fetched from brackets.config.contributors_url using the github API.
* If more than 2 weeks have passed since the last fetch, or if cached data can't be found,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part of the comment is now out of date.

* the data is fetched again.
* @return {$.Promise} jQuery Promise object that is resolved or rejected after the information is fetched.
*/
function _getContributorsInformation() {
var result = new $.Deferred();
var fetchData = false;
var data;

// If we don't have data saved in prefs, fetch
data = _prefs.getValue("contributorsInfo");
if (!data) {
fetchData = true;
}

// If more than 2 weeks have passed since our last fetch, fetch again
if ((new Date()).getTime() > _lastContributorsFetchTime + (14 * 24 * 60 * 60 * 24)) {
fetchData = true;
}

if (fetchData) {
$.getJSON(brackets.config.contributors_url + "?callback=?", function (contributorsInfo) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because GitHub uses the Access-Control-Allow-Origin: *, would it be better to use a regular get as opposed to a getJSON which injects an unnecessary script element into the page?

$.get(brackets.config.contributors_url, function (contributorsInfo) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see any difference in how getJSON would be any different to get, since actually getJSON is used with a dataType of JSONP. But you might know better and I could even simply make it a $.ajax with a dataType: "jsonp" setting if is a better solution.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually not $.get vs $.getJSON but rather the inclusion of ?callback=?. This triggers the dataType: "jsonp" which wraps the data in a callback on the server, and then includes a script element in the page, which is a) unnecessary in this case, and b) is significantly slower.

I put together a quick test at http://jsperf.com/get-vs-getjson-vs-ajax which shows the performance hit that dataType: "jsonp" takes.

data = [];

// Save only the required data for the template
$.each(contributorsInfo.data, function (index, element) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use forEach() instead of $.each()

data.push({
GITHUB_URL : element.html_url,
AVATAR_URL : element.avatar_url,
NAME : element.login
});
});
_lastContributorsFetchTime = (new Date()).getTime();
_prefs.setValue("lastContributorsFetchTime", _lastContributorsFetchTime);
_prefs.setValue("contributorsInfo", data);

result.resolve(data);

}).error(function () {
result.reject();
});
} else {
result.resolve(data);
}

return result.promise();
}


function _handleCheckForUpdates() {
UpdateNotification.checkForUpdate(true);
}
Expand All @@ -69,7 +131,39 @@ define(function (require, exports, module) {
APP_NAME_ABOUT_BOX : brackets.config.app_name_about,
BUILD_INFO : buildInfo || ""
}, Strings);

Dialogs.showModalDialogUsingTemplate(Mustache.render(AboutDialogTemplate, templateVars));

// Get all the project contributors and add them to the dialog
_getContributorsInformation().done(function (contributorsInfo) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this is, but there seems to be a long pause before the About dialog appears now (compared to master). I don't know why that should be, because the fetch of the contributor info is asynchronous, so it shouldn't actually block the dialog from appearing. Are you seeing that at all? If so, any ideas what could be happening?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Long pause seems to be gone.


// Populate the contributors data
var $dlg = $(".about-dialog.instance");
var $contributors = $dlg.find(".about-contributors");

templateVars = $.extend({CONTRIBUTORS: contributorsInfo}, Strings);
$contributors.html(Mustache.render(ContributorsTemplate, templateVars));

// This is used to create an opacity transition when each image is loaded
$dlg.find("img").one("load", function () {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be $contributors.find("img") so it doesn't affect other images in the dialog (like the Brackets icon).

$(this).css("opacity", 1);
}).each(function () {
if (this.complete) {
$(this).load();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not clear on what this does. jQuery has two load() methods, but neither of them seem to be relevant here: one takes a url argument and replaces the content of the current element with the fetched content from the URL; the other binds an event handler to the "load" event.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it should be a trigger("load") used just to trigger the event for cached images that supposedly don't trigger the load event by themselves. But it has been working with that until now, so I am not sure if it really does what it supposed to do.

}
});

$dlg.on("click", "img", function (e) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly, this should be $contributors.on(...)

var url = $(e.target).data("url");

if (url) {
// Make sure the URL has a domain that we know about
if (/(github\.com)$/i.test(PathUtils.parseUrl(url).hostname)) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure under what scenario a malicious website could end up in here, but if the goal is to guard against that, the regexp should be something like /(^|\.)github\.com$/ (so a site like "myfakegithub.com" wouldn't match).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should I just remove this then?

NativeApp.openURLInDefaultBrowser(url);
}
}
});
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, there should be a fail() case here that turns the spinner off and maybe adds something like: "Lots of people (but we can't access github right now to find out who)."

}

// Read "build number" SHAs off disk immediately at APP_READY, instead
Expand Down
13 changes: 9 additions & 4 deletions src/htmlContent/about-dialog.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@ <h1 class="dialog-title">{{ABOUT}}</h1>
<img class="about-icon" src="{{ABOUT_ICON}}">
<div class="about-text">
<h2>{{APP_NAME_ABOUT_BOX}}</h2>
<p class="dialog-message">{{ABOUT_TEXT_LINE1}} <span id="about-build-number">{{BUILD_INFO}}</span></p>
<p class="dialog-message"><!-- $NON-NLS$ -->Copyright 2012 - 2013 Adobe Systems Incorporated and its licensors. All rights reserved.</p>
<p class="dialog-message">{{{ABOUT_TEXT_LINE3}}}</p>
<p class="dialog-message">{{{ABOUT_TEXT_LINE4}}}</p>
<div class="about-info">
<p class="dialog-message">{{ABOUT_TEXT_LINE1}} <span id="about-build-number">{{BUILD_INFO}}</span></p>
<p class="dialog-message"><!-- $NON-NLS$ -->Copyright 2012 - 2013 Adobe Systems Incorporated and its licensors. All rights reserved.</p>
<p class="dialog-message">{{{ABOUT_TEXT_LINE3}}}</p>
<p class="dialog-message">{{{ABOUT_TEXT_LINE4}}}</p>
<p class="dialog-message">{{ABOUT_TEXT_LINE5}}</p>
<div class="about-contributors">
</div>
</div>
</div>
</div>
<div class="modal-footer">
Expand Down
3 changes: 3 additions & 0 deletions src/htmlContent/contributors-list.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{{#CONTRIBUTORS}}
<img class="clickable-link" data-url="{{GITHUB_URL}}" src="{{AVATAR_URL}}" title="{{NAME}}" alt="{{NAME}}" width="30" height="30" />
{{/CONTRIBUTORS}}
1 change: 1 addition & 0 deletions src/nls/root/strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ define({
"ABOUT_TEXT_LINE1" : "sprint {VERSION_MINOR} {BUILD_TYPE} {VERSION}",
"ABOUT_TEXT_LINE3" : "Notices, terms and conditions pertaining to third party software are located at <a class=\"clickable-link\" data-href=\"http://www.adobe.com/go/thirdparty/\">http://www.adobe.com/go/thirdparty/</a> and incorporated by reference herein.",
"ABOUT_TEXT_LINE4" : "Documentation and source at <a class=\"clickable-link\" data-href=\"https://github.com/adobe/brackets/\">https://github.com/adobe/brackets/</a>",
"ABOUT_TEXT_LINE5" : "Made with \u2764 and JavaScript by:",
"UPDATE_NOTIFICATION_TOOLTIP" : "There's a new build of {APP_NAME} available! Click here for details.",
"UPDATE_AVAILABLE_TITLE" : "Update Available",
"UPDATE_MESSAGE" : "Hey, there's a new build of {APP_NAME} available. Here are some of the new features:",
Expand Down
16 changes: 16 additions & 0 deletions src/styles/brackets_patterns_override.less
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,22 @@
#about-build-number {
color: #b0b0b0;
}
.about-info {
max-height: 300px;
overflow: auto;
}
.about-contributors {
min-width: 395px;
min-height: 100px;
background-color: whiteSmoke;
}
.about-contributors img {
opacity: 0;
-webkit-transition: opacity 1s;
-moz-transition: opacity 1s;
-o-transition: opacity 1s;
transition: opacity 1s;
}
}

h2 {
Expand Down