Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
9
gaia/distros/spark/apps/directory/js/app.js
Executable file
9
gaia/distros/spark/apps/directory/js/app.js
Executable file
|
|
@ -0,0 +1,9 @@
|
|||
define(["exports", "js/globals", "js/controller/main_controller"], function (exports, _jsGlobals, _jsControllerMainController) {
|
||||
"use strict";
|
||||
|
||||
var MainController = _jsControllerMainController["default"];
|
||||
|
||||
|
||||
var mainController = new MainController();
|
||||
mainController.main();
|
||||
});
|
||||
258
gaia/distros/spark/apps/directory/js/controller/list_controller.js
Executable file
258
gaia/distros/spark/apps/directory/js/controller/list_controller.js
Executable file
|
|
@ -0,0 +1,258 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "js/model/list_model", "js/view/tabs_view", "js/view/offline_view", "js/view/app_list_view", "js/view/addon_list_view", "js/view/details_view"], function (exports, _componentsFxosMvcDistMvc, _jsModelListModel, _jsViewTabsView, _jsViewOfflineView, _jsViewAppListView, _jsViewAddonListView, _jsViewDetailsView) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var Controller = _componentsFxosMvcDistMvc.Controller;
|
||||
var ListModel = _jsModelListModel["default"];
|
||||
var TabsView = _jsViewTabsView["default"];
|
||||
var OfflineView = _jsViewOfflineView["default"];
|
||||
var AppListView = _jsViewAppListView["default"];
|
||||
var AddonListView = _jsViewAddonListView["default"];
|
||||
var DetailsView = _jsViewDetailsView["default"];
|
||||
var ListController = (function (Controller) {
|
||||
var ListController = function ListController() {
|
||||
this.installedApps = Object.create(null);
|
||||
|
||||
this.model = new ListModel();
|
||||
this.tabsView = new TabsView();
|
||||
this.offlineView = new OfflineView();
|
||||
this.appView = new AppListView();
|
||||
this.addonView = new AddonListView();
|
||||
this.detailsView = new DetailsView();
|
||||
|
||||
this.tabsView.onTabChange(this.handleTabChange.bind(this));
|
||||
document.addEventListener("visibilitychange", this.refreshInstalledList.bind(this));
|
||||
};
|
||||
|
||||
_extends(ListController, Controller);
|
||||
|
||||
ListController.prototype.main = function () {
|
||||
var hash = window.location.hash;
|
||||
var tab = hash && hash.slice(1);
|
||||
|
||||
if (!this.initialized) {
|
||||
this.createList(tab);
|
||||
}
|
||||
this.activateTab(tab);
|
||||
};
|
||||
|
||||
ListController.prototype.showAlertDialog = function (msg) {
|
||||
this.alertDialog.textContent = msg;
|
||||
this.alertDialog.open();
|
||||
};
|
||||
|
||||
ListController.prototype.createList = function (tab) {
|
||||
this.offlineView.render();
|
||||
document.body.appendChild(this.offlineView.el);
|
||||
this.tabsView.render(tab);
|
||||
document.body.appendChild(this.tabsView.el);
|
||||
this.appView.render();
|
||||
document.body.appendChild(this.appView.el);
|
||||
this.addonView.render();
|
||||
document.body.appendChild(this.addonView.el);
|
||||
this.detailsView.render();
|
||||
document.body.appendChild(this.detailsView.el);
|
||||
this.alertDialog = document.body.querySelector("#alert-dialog");
|
||||
|
||||
this.appView.onInstall(this.handleInstall.bind(this));
|
||||
this.addonView.onInstall(this.handleInstall.bind(this));
|
||||
this.appView.onDetails(this.handleDetails.bind(this));
|
||||
this.addonView.onDetails(this.handleDetails.bind(this));
|
||||
this.detailsView.onClose(this.handleCloseDetails.bind(this));
|
||||
this.detailsView.onInstall(this.handleInstall.bind(this));
|
||||
|
||||
this.getApps();
|
||||
this.watchConnection();
|
||||
|
||||
this.initialized = true;
|
||||
};
|
||||
|
||||
ListController.prototype.getApps = function () {
|
||||
var _this = this;
|
||||
this.model.getAppList().then(function (list) {
|
||||
_this.list = list;
|
||||
_this.refreshInstalledList();
|
||||
});
|
||||
};
|
||||
|
||||
ListController.prototype.watchConnection = function () {
|
||||
window.addEventListener("online", this.handleConnection.bind(this));
|
||||
window.addEventListener("offline", this.handleConnection.bind(this));
|
||||
this.handleConnection();
|
||||
};
|
||||
|
||||
ListController.prototype.handleConnection = function () {
|
||||
var online = navigator.onLine;
|
||||
this.offlineView.update(online);
|
||||
if (online) {
|
||||
this.getApps();
|
||||
}
|
||||
};
|
||||
|
||||
ListController.prototype.refreshInstalledList = function () {
|
||||
var _this2 = this;
|
||||
this.installedApps = Object.create(null);
|
||||
|
||||
// Use mgmt.getAll if available to fetch apps,
|
||||
// otherwise use mozApp.getInstalled.
|
||||
var req;
|
||||
if (navigator.mozApps.mgmt && navigator.mozApps.mgmt.getAll) {
|
||||
req = navigator.mozApps.mgmt.getAll();
|
||||
} else {
|
||||
req = navigator.mozApps.getInstalled();
|
||||
}
|
||||
|
||||
req.onsuccess = function () {
|
||||
var apps = req.result;
|
||||
var installedApps = Object.create(null);
|
||||
apps.forEach(function (app) {
|
||||
installedApps[app.manifestURL] = app;
|
||||
});
|
||||
for (var manifestURL in _this2.list) {
|
||||
_this2.list[manifestURL].installed = !!installedApps[manifestURL];
|
||||
_this2.list[manifestURL].mozApp = installedApps[manifestURL] || false;
|
||||
if (_this2.detailsView.isShowing(manifestURL)) {
|
||||
// If it's showing, repopulate the details view with new app data.
|
||||
_this2.detailsView.show(_this2.list[manifestURL]);
|
||||
}
|
||||
}
|
||||
_this2.appView.update(_this2.list);
|
||||
_this2.addonView.update(_this2.list);
|
||||
};
|
||||
|
||||
req.onerror = function (e) {
|
||||
_this2.showAlertDialog("error fetching install apps: " + e.message);
|
||||
console.log("error fetching installed apps: ", e);
|
||||
};
|
||||
};
|
||||
|
||||
ListController.prototype.handleTabChange = function (activeTab) {
|
||||
// Changing the hash will eventually invoke activateTab, however we
|
||||
// call it here directly to make the switch animation happen faster.
|
||||
this.activateTab(activeTab);
|
||||
window.location.hash = "#" + activeTab;
|
||||
};
|
||||
|
||||
ListController.prototype.activateTab = function (activeTab) {
|
||||
if (this.activeTab === activeTab) {
|
||||
return;
|
||||
}
|
||||
this.activeTab = activeTab;
|
||||
|
||||
if (activeTab === "apps") {
|
||||
this.appView.activate();
|
||||
this.addonView.deactivate();
|
||||
} else {
|
||||
this.addonView.activate();
|
||||
this.appView.deactivate();
|
||||
}
|
||||
};
|
||||
|
||||
ListController.prototype.handleInstall = function (data) {
|
||||
var manifestURL = data.manifestURL;
|
||||
if (this.list[manifestURL].mozApp) {
|
||||
// Addons cannot be launched so do nothing on button click.
|
||||
if (data.type !== "addon") {
|
||||
this.list[manifestURL].mozApp.launch();
|
||||
}
|
||||
} else {
|
||||
this.install(data);
|
||||
}
|
||||
};
|
||||
|
||||
ListController.prototype.handleDetails = function (manifestURL) {
|
||||
this.detailsView.show(this.list[manifestURL]);
|
||||
};
|
||||
|
||||
ListController.prototype.handleCloseDetails = function () {
|
||||
this.detailsView.hide();
|
||||
this.refreshInstalledList();
|
||||
};
|
||||
|
||||
ListController.prototype.install = function (appData) {
|
||||
var _this3 = this;
|
||||
var manifest = appData.manifestURL;
|
||||
var type = appData.type;
|
||||
var installReq;
|
||||
if (type === "hosted") {
|
||||
console.log("installing hosted app, ", manifest);
|
||||
installReq = navigator.mozApps.install(manifest, {
|
||||
installMetaData: {
|
||||
url: appData.url,
|
||||
revision: appData.revision
|
||||
}
|
||||
});
|
||||
} else if (type === "packaged" || type === "addon") {
|
||||
console.log("installing packaged app, ", manifest);
|
||||
installReq = navigator.mozApps.installPackage(manifest, {
|
||||
installMetaData: {
|
||||
url: appData.url,
|
||||
revision: appData.revision
|
||||
}
|
||||
});
|
||||
} else {
|
||||
throw new Error("Could not install app, unrecognized type: " + type);
|
||||
}
|
||||
|
||||
installReq.onerror = function (err) {
|
||||
var errorMsg;
|
||||
var errorType = err.target.error.name;
|
||||
switch (errorType) {
|
||||
case "DENIED":
|
||||
// If the user cancelled the install, we do nothing.
|
||||
return;
|
||||
|
||||
case "NETWORK_ERROR":
|
||||
errorMsg = "No network";
|
||||
break;
|
||||
|
||||
case "MANIFEST_URL_ERROR":
|
||||
errorMsg = "Invalid manifest url";
|
||||
break;
|
||||
|
||||
case "INVALID_SECURITY_LEVEL":
|
||||
errorMsg = "Invalid permissions, try enabling developer mode";
|
||||
break;
|
||||
|
||||
default:
|
||||
errorMsg = errorType;
|
||||
break;
|
||||
}
|
||||
|
||||
_this3.showAlertDialog("INSTALL ERROR: " + errorMsg);
|
||||
};
|
||||
|
||||
installReq.onsuccess = function () {
|
||||
if (type === "addon") {
|
||||
// Enable add-ons immediately by default.
|
||||
navigator.mozApps.mgmt.setEnabled(installReq.result, true);
|
||||
}
|
||||
_this3.refreshInstalledList();
|
||||
window.dispatchEvent(new CustomEvent("achievement-rewarded", {
|
||||
detail: {
|
||||
criteria: "achievements/fab-finder",
|
||||
evidence: "urn:fxos-directory:app:installed",
|
||||
name: "Fab Finder",
|
||||
description: "Install an app or add-on from Hackerplace",
|
||||
image: "./img/fab-finder.png"
|
||||
}
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
return ListController;
|
||||
})(Controller);
|
||||
|
||||
exports["default"] = ListController;
|
||||
});
|
||||
69
gaia/distros/spark/apps/directory/js/controller/main_controller.js
Executable file
69
gaia/distros/spark/apps/directory/js/controller/main_controller.js
Executable file
|
|
@ -0,0 +1,69 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "gaia-component", "gaia-dialog", "js/view/main_view", "js/controller/list_controller", "js/view/upload_view.js", "js/lib/helpers"], function (exports, _componentsFxosMvcDistMvc, _gaiaComponent, _gaiaDialog, _jsViewMainView, _jsControllerListController, _jsViewUploadViewJs, _jsLibHelpers) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var RoutingController = _componentsFxosMvcDistMvc.RoutingController;
|
||||
var MainView = _jsViewMainView["default"];
|
||||
var ListController = _jsControllerListController["default"];
|
||||
var UploadView = _jsViewUploadViewJs["default"];
|
||||
var ActivityHelper = _jsLibHelpers.ActivityHelper;
|
||||
var AchievementsHelper = _jsLibHelpers.AchievementsHelper;
|
||||
var MainController = (function (RoutingController) {
|
||||
var MainController = function MainController() {
|
||||
this.view = new MainView({ el: document.body });
|
||||
this.activityHelper = new ActivityHelper();
|
||||
this.achievementsHelper = new AchievementsHelper();
|
||||
this.listController = new ListController();
|
||||
RoutingController.call(this, {
|
||||
apps: this.listController,
|
||||
addons: this.listController
|
||||
});
|
||||
};
|
||||
|
||||
_extends(MainController, RoutingController);
|
||||
|
||||
MainController.prototype.main = function () {
|
||||
var _this = this;
|
||||
this.activityHelper.ready.then(function (route) {
|
||||
_this.view.render(_this.activityHelper.isActivity);
|
||||
// We cannot upload from the activity.
|
||||
if (!_this.activityHelper.isActivity) {
|
||||
_this.renderUploadView();
|
||||
}
|
||||
|
||||
// If current hash does not match current route, change the hash
|
||||
// to invoke routing function, otherwise invoke route explicitly.
|
||||
if (window.location.hash.slice(1) !== route) {
|
||||
window.location.hash = "#" + route;
|
||||
} else {
|
||||
_this.route();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
MainController.prototype.renderUploadView = function () {
|
||||
var _this2 = this;
|
||||
this.uploadView = new UploadView();
|
||||
this.uploadView.render();
|
||||
this.view.el.appendChild(this.uploadView.el);
|
||||
this.view.onUpload(function () {
|
||||
_this2.uploadView.show();
|
||||
});
|
||||
};
|
||||
|
||||
return MainController;
|
||||
})(RoutingController);
|
||||
|
||||
exports["default"] = MainController;
|
||||
});
|
||||
14
gaia/distros/spark/apps/directory/js/globals.js
Executable file
14
gaia/distros/spark/apps/directory/js/globals.js
Executable file
|
|
@ -0,0 +1,14 @@
|
|||
define(["exports"], function (exports) {
|
||||
"use strict";
|
||||
|
||||
window.COMPONENTS_BASE_URL = "./components/";
|
||||
window.DEFAULT_ICON_URL = "./img/default_icon.png";
|
||||
require.config({
|
||||
baseUrl: "/",
|
||||
paths: {
|
||||
"gaia-dialog": "components/gaia-dialog/gaia-dialog",
|
||||
"gaia-component": "components/gaia-component/gaia-component",
|
||||
"gaia-icons": "components/gaia-icons/gaia-icons"
|
||||
}
|
||||
});
|
||||
});
|
||||
1429
gaia/distros/spark/apps/directory/js/initapp.js
Executable file
1429
gaia/distros/spark/apps/directory/js/initapp.js
Executable file
File diff suppressed because it is too large
Load diff
120
gaia/distros/spark/apps/directory/js/lib/helpers.js
Executable file
120
gaia/distros/spark/apps/directory/js/lib/helpers.js
Executable file
|
|
@ -0,0 +1,120 @@
|
|||
define(["exports", "components/fxos-achievements-service/dist/achievements-service"], function (exports, _componentsFxosAchievementsServiceDistAchievementsService) {
|
||||
"use strict";
|
||||
|
||||
var AchievementsService = _componentsFxosAchievementsServiceDistAchievementsService["default"];
|
||||
var IconHelper = (function () {
|
||||
var IconHelper = function IconHelper() {};
|
||||
|
||||
IconHelper.setImage = function (imageElement, imagePath) {
|
||||
imageElement.src = imagePath || window.DEFAULT_ICON_URL;
|
||||
imageElement.onerror = function (e) {
|
||||
console.warn("Warning, failed to load icon url", imageElement.src, e);
|
||||
imageElement.src = window.DEFAULT_ICON_URL;
|
||||
};
|
||||
};
|
||||
|
||||
return IconHelper;
|
||||
})();
|
||||
|
||||
exports.IconHelper = IconHelper;
|
||||
var AppsHelper = (function () {
|
||||
var AppsHelper = function AppsHelper() {};
|
||||
|
||||
AppsHelper.getAllApps = function () {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var mgmt = navigator.mozApps.mgmt;
|
||||
if (!mgmt) {
|
||||
reject(new Error("Cannot fetch apps, no permissions"));
|
||||
}
|
||||
|
||||
var req = mgmt.getAll();
|
||||
req.onsuccess = function () {
|
||||
resolve(req.result);
|
||||
};
|
||||
req.onerror = function (e) {
|
||||
reject(e);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
return AppsHelper;
|
||||
})();
|
||||
|
||||
exports.AppsHelper = AppsHelper;
|
||||
var ManifestHelper = (function () {
|
||||
var ManifestHelper = function ManifestHelper() {};
|
||||
|
||||
ManifestHelper.getManifest = function (url) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var req = new XMLHttpRequest();
|
||||
req.open("GET", url, true);
|
||||
req.responseType = "json";
|
||||
req.onload = function () {
|
||||
resolve(req.response);
|
||||
};
|
||||
req.onerror = function (e) {
|
||||
reject(e);
|
||||
};
|
||||
req.send();
|
||||
});
|
||||
};
|
||||
|
||||
ManifestHelper.hasHigherPriviledges = function (manifest1, manifest2) {
|
||||
return manifest1.type === manifest2.type || manifest1.type === "certified" || (manifest1.type === "privileged" && manifest2.type !== "certified");
|
||||
};
|
||||
|
||||
return ManifestHelper;
|
||||
})();
|
||||
|
||||
exports.ManifestHelper = ManifestHelper;
|
||||
var ActivityHelper = (function () {
|
||||
var ActivityHelper = function ActivityHelper() {
|
||||
var _this = this;
|
||||
this.ready = new Promise(function (resolve, reject) {
|
||||
if (navigator.mozHasPendingMessage && navigator.mozHasPendingMessage("activity")) {
|
||||
navigator.mozSetMessageHandler("activity", function (activity) {
|
||||
var activitySource = activity.source;
|
||||
|
||||
if (activitySource.name !== "install") {
|
||||
activity.postError("Unsupported activity");
|
||||
return;
|
||||
}
|
||||
|
||||
_this.isActivity = true;
|
||||
window.addEventListener("request-activity-finish", function () {
|
||||
activity.postResult("finished");
|
||||
});
|
||||
resolve(_this.getRoute(activitySource.data.type));
|
||||
});
|
||||
} else {
|
||||
var hash = window.location.hash;
|
||||
resolve(_this.getRoute(hash && hash.slice(1)));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
ActivityHelper.prototype.getRoute = function (type) {
|
||||
return type || "apps";
|
||||
};
|
||||
|
||||
return ActivityHelper;
|
||||
})();
|
||||
|
||||
exports.ActivityHelper = ActivityHelper;
|
||||
var AchievementsHelper = (function () {
|
||||
var AchievementsHelper = function AchievementsHelper() {
|
||||
// Create an achievements service
|
||||
this.achievementsService = new AchievementsService();
|
||||
|
||||
window.addEventListener("achievement-rewarded", this);
|
||||
};
|
||||
|
||||
AchievementsHelper.prototype.handleEvent = function (aEvent) {
|
||||
this.achievementsService.reward(aEvent.detail);
|
||||
};
|
||||
|
||||
return AchievementsHelper;
|
||||
})();
|
||||
|
||||
exports.AchievementsHelper = AchievementsHelper;
|
||||
});
|
||||
75
gaia/distros/spark/apps/directory/js/model/list_model.js
Executable file
75
gaia/distros/spark/apps/directory/js/model/list_model.js
Executable file
|
|
@ -0,0 +1,75 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc"], function (exports, _componentsFxosMvcDistMvc) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var Model = _componentsFxosMvcDistMvc.Model;
|
||||
|
||||
|
||||
var DEBUG = 0;
|
||||
|
||||
var ListModel = (function (Model) {
|
||||
var ListModel = function ListModel() {
|
||||
Model.apply(this, arguments);
|
||||
};
|
||||
|
||||
_extends(ListModel, Model);
|
||||
|
||||
ListModel.prototype.getAppList = function () {
|
||||
var _this = this;
|
||||
return new Promise(function (resolve, reject) {
|
||||
var localApps = _this.loadApps("/apps-v2.json");
|
||||
var remoteApps = _this.loadApps("http://directory.fxosapps.org/apps-v2.json");
|
||||
Promise.all([localApps, remoteApps]).then(function (sources) {
|
||||
localApps = sources[0];
|
||||
remoteApps = sources[1];
|
||||
|
||||
// Try to fetch the remote app list, but if it fails, use the packaged
|
||||
// one instead.
|
||||
if (DEBUG || Object.keys(remoteApps).length < 1) {
|
||||
resolve(localApps);
|
||||
} else {
|
||||
resolve(remoteApps);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
ListModel.prototype.loadApps = function (url) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
var xhr = new XMLHttpRequest({ mozSystem: true, mozAnon: true });
|
||||
xhr.open("GET", url, true);
|
||||
xhr.responseType = "json";
|
||||
xhr.onload = function () {
|
||||
var apps = {};
|
||||
if (xhr.status === 200) {
|
||||
apps = xhr.response;
|
||||
localStorage.setItem("apps", JSON.stringify(apps));
|
||||
} else {
|
||||
console.log("Error fetching app list", xhr.status);
|
||||
}
|
||||
resolve(apps);
|
||||
};
|
||||
xhr.onerror = function (e) {
|
||||
console.log("Error fetching app list", e);
|
||||
resolve({});
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
};
|
||||
|
||||
return ListModel;
|
||||
})(Model);
|
||||
|
||||
exports["default"] = ListModel;
|
||||
});
|
||||
39
gaia/distros/spark/apps/directory/js/view/addon_list_view.js
Executable file
39
gaia/distros/spark/apps/directory/js/view/addon_list_view.js
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
define(["exports", "js/view/list_view"], function (exports, _jsViewListView) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var ListView = _jsViewListView["default"];
|
||||
var AddonListView = (function (ListView) {
|
||||
var AddonListView = function AddonListView() {
|
||||
ListView.call(this);
|
||||
this.el.id = "addon-list";
|
||||
};
|
||||
|
||||
_extends(AddonListView, ListView);
|
||||
|
||||
AddonListView.prototype.update = function (list) {
|
||||
var addonList = {};
|
||||
for (var manifestURL in list) {
|
||||
if (list[manifestURL].type === "addon") {
|
||||
addonList[manifestURL] = list[manifestURL];
|
||||
}
|
||||
}
|
||||
ListView.prototype.update.call(this, addonList);
|
||||
};
|
||||
|
||||
return AddonListView;
|
||||
})(ListView);
|
||||
|
||||
exports["default"] = AddonListView;
|
||||
});
|
||||
39
gaia/distros/spark/apps/directory/js/view/app_list_view.js
Executable file
39
gaia/distros/spark/apps/directory/js/view/app_list_view.js
Executable file
|
|
@ -0,0 +1,39 @@
|
|||
define(["exports", "js/view/list_view"], function (exports, _jsViewListView) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var ListView = _jsViewListView["default"];
|
||||
var AppListView = (function (ListView) {
|
||||
var AppListView = function AppListView() {
|
||||
ListView.call(this);
|
||||
this.el.id = "app-list";
|
||||
};
|
||||
|
||||
_extends(AppListView, ListView);
|
||||
|
||||
AppListView.prototype.update = function (list) {
|
||||
var appList = {};
|
||||
for (var manifestURL in list) {
|
||||
if (list[manifestURL].type !== "addon") {
|
||||
appList[manifestURL] = list[manifestURL];
|
||||
}
|
||||
}
|
||||
ListView.prototype.update.call(this, appList);
|
||||
};
|
||||
|
||||
return AppListView;
|
||||
})(ListView);
|
||||
|
||||
exports["default"] = AppListView;
|
||||
});
|
||||
185
gaia/distros/spark/apps/directory/js/view/details_view.js
Executable file
185
gaia/distros/spark/apps/directory/js/view/details_view.js
Executable file
|
|
@ -0,0 +1,185 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-header/dist/gaia-header", "components/gaia-sub-header/gaia-sub-header", "components/gaia-list/gaia-list", "components/gaia-button/gaia-button", "js/lib/helpers"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaHeaderDistGaiaHeader, _componentsGaiaSubHeaderGaiaSubHeader, _componentsGaiaListGaiaList, _componentsGaiaButtonGaiaButton, _jsLibHelpers) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var IconHelper = _jsLibHelpers.IconHelper;
|
||||
var AppsHelper = _jsLibHelpers.AppsHelper;
|
||||
var ManifestHelper = _jsLibHelpers.ManifestHelper;
|
||||
|
||||
|
||||
function capitalize(string) {
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
var DetailsView = (function (View) {
|
||||
var DetailsView = function DetailsView() {
|
||||
this.el = document.createElement("div");
|
||||
this.el.id = "app-details";
|
||||
this.el.classList.add("popup");
|
||||
this.closeHandlers = [];
|
||||
this.installHandlers = [];
|
||||
};
|
||||
|
||||
_extends(DetailsView, View);
|
||||
|
||||
DetailsView.prototype.render = function () {
|
||||
var _this = this;
|
||||
View.prototype.render.call(this);
|
||||
this.titleElement = this.el.querySelector("#details-title");
|
||||
this.itemElement = this.el.querySelector(".item");
|
||||
this.nameElement = this.el.querySelector(".name");
|
||||
this.iconElement = this.el.querySelector(".icon");
|
||||
this.authorElement = this.el.querySelector(".author");
|
||||
this.fullDescription = this.el.querySelector("#full-description");
|
||||
this.addonSection = this.el.querySelector("#addon-section");
|
||||
this.affectedApps = this.el.querySelector("#affected-apps");
|
||||
this.installButton = this.el.querySelector(".install-button");
|
||||
this.repoLink = this.el.querySelector("#repo-link");
|
||||
|
||||
this.installButton.addEventListener("click", function () {
|
||||
_this.installHandlers.forEach(function (handler) {
|
||||
handler(_this.details);
|
||||
});
|
||||
});
|
||||
this.closeButton = this.el.querySelector("#close-button");
|
||||
this.closeButton.addEventListener("click", function () {
|
||||
_this.closeHandlers.forEach(function (handler) {
|
||||
handler();
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
DetailsView.prototype.filterNonAffectedApps = function (apps, addonManifest) {
|
||||
var filters = addonManifest.customizations.map(function (customization) {
|
||||
return new RegExp(customization.filter);
|
||||
});
|
||||
|
||||
return apps.filter(function (app) {
|
||||
if (!app.manifest) {
|
||||
console.log("Could not filter app, manifest not found", app.name);
|
||||
return false;
|
||||
}
|
||||
// Make sure the addon has appropriate privs against the app.
|
||||
if (!ManifestHelper.hasHigherPriviledges(addonManifest, app.manifest)) {
|
||||
return false;
|
||||
}
|
||||
// Test the apps launch URL against each customization filter
|
||||
// and mark the app as affected if it matches at least one.
|
||||
var launchPath = app.manifest.launch_path || "";
|
||||
var launchURL = new URL(launchPath, app.manifestURL).href;
|
||||
return filters.find(function (filter) {
|
||||
return filter.test(launchURL);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
DetailsView.prototype.dedupeAppNames = function (apps) {
|
||||
return apps.map(function (app) {
|
||||
return app.manifest.name;
|
||||
}).filter(function (appName, index, appNames) {
|
||||
return appNames.indexOf(appName) === index;
|
||||
});
|
||||
};
|
||||
|
||||
DetailsView.prototype.populateAffectedApps = function (details) {
|
||||
var _this2 = this;
|
||||
Promise.all([AppsHelper.getAllApps(), ManifestHelper.getManifest(details.manifestURL)]).then(function (results) {
|
||||
var apps = results[0];
|
||||
var addonManifest = results[1];
|
||||
if (!addonManifest) {
|
||||
// If we cannot fetch addon manifest, we cannot display addon info.
|
||||
_this2.affectedApps.textContent = "Cannot determine affected apps, invalid manifest URL.";
|
||||
} else {
|
||||
var filteredApps = _this2.filterNonAffectedApps(apps, addonManifest);
|
||||
|
||||
var affectedAppList;
|
||||
if (apps.length === filteredApps.length) {
|
||||
affectedAppList = "All applications.";
|
||||
} else {
|
||||
affectedAppList = _this2.dedupeAppNames(filteredApps).join(", ");
|
||||
}
|
||||
_this2.affectedApps.textContent = affectedAppList || "None";
|
||||
}
|
||||
})["catch"](function (err) {
|
||||
console.warn("Could not populate affected apps", err);
|
||||
// Hide affected apps section when undetermined.
|
||||
_this2.addonSection.hidden = true;
|
||||
});
|
||||
};
|
||||
|
||||
DetailsView.prototype.show = function (details) {
|
||||
this.details = details;
|
||||
this.itemElement.classList.toggle("installed", details.installed);
|
||||
this.itemElement.classList.toggle("addon", (details.type === "addon"));
|
||||
this.titleElement.textContent = capitalize(details.name);
|
||||
IconHelper.setImage(this.iconElement, details.icon);
|
||||
this.nameElement.textContent = capitalize(details.name);
|
||||
this.authorElement.textContent = details.author;
|
||||
this.fullDescription.textContent = details.description;
|
||||
this.installButton.textContent = details.installed ? "Open" : "Install";
|
||||
this.installButton.classList.toggle("installed", details.installed);
|
||||
this.installButton.disabled = false;
|
||||
this.addonSection.hidden = true;
|
||||
if (details.url) {
|
||||
this.repoLink.parentElement.hidden = false;
|
||||
this.repoLink.href = details.url;
|
||||
this.repoLink.textContent = details.url;
|
||||
} else {
|
||||
this.repoLink.parentElement.hidden = true;
|
||||
}
|
||||
|
||||
// Addons need the affected apps section, and no Open button.
|
||||
if (details.type === "addon") {
|
||||
if (details.installed) {
|
||||
this.installButton.textContent = "Installed";
|
||||
this.installButton.disabled = true;
|
||||
}
|
||||
this.addonSection.hidden = false;
|
||||
this.populateAffectedApps(details);
|
||||
}
|
||||
|
||||
this.el.classList.add("active");
|
||||
};
|
||||
|
||||
DetailsView.prototype.hide = function () {
|
||||
this.el.classList.remove("active");
|
||||
};
|
||||
|
||||
DetailsView.prototype.isShowing = function (manifestURL) {
|
||||
return this.el.classList.contains("active") && this.details.manifestURL === manifestURL;
|
||||
};
|
||||
|
||||
DetailsView.prototype.onClose = function (handler) {
|
||||
if (this.closeHandlers.indexOf(handler) === -1) {
|
||||
this.closeHandlers.push(handler);
|
||||
}
|
||||
};
|
||||
|
||||
DetailsView.prototype.onInstall = function (handler) {
|
||||
if (this.installHandlers.indexOf(handler) === -1) {
|
||||
this.installHandlers.push(handler);
|
||||
}
|
||||
};
|
||||
|
||||
DetailsView.prototype.template = function () {
|
||||
var string = "\n <gaia-header>\n <a id=\"close-button\" class=\"close\"><i data-icon=\"close\"></i></a>\n <h1 id=\"details-title\">App Details</h1>\n </gaia-header>\n <gaia-list class=\"info-list install-list\">\n <li class=\"item\">\n <img class=\"icon\" />\n <div flex class=\"description\">\n <p class=\"name\"></p>\n <p class=\"author\"></p>\n </div>\n <span class=\"install-info\">Installed</span>\n <gaia-button class=\"install-button\"></gaia-button>\n </li>\n </gaia-list>\n <p id=\"full-description\"></p>\n <p id=\"repo\"><a target=\"_blank\" id=\"repo-link\"></a></p>\n <div id=\"addon-section\">\n <gaia-sub-header>Affected Apps</gaia-sub-header>\n <p id=\"affected-apps\"></div>\n </div>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return DetailsView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = DetailsView;
|
||||
});
|
||||
126
gaia/distros/spark/apps/directory/js/view/list_view.js
Executable file
126
gaia/distros/spark/apps/directory/js/view/list_view.js
Executable file
|
|
@ -0,0 +1,126 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-list/gaia-list", "components/gaia-button/gaia-button", "js/lib/helpers"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaListGaiaList, _componentsGaiaButtonGaiaButton, _jsLibHelpers) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var IconHelper = _jsLibHelpers.IconHelper;
|
||||
|
||||
|
||||
function capitalize(string) {
|
||||
return string[0].toUpperCase() + string.slice(1);
|
||||
}
|
||||
|
||||
var ListView = (function (View) {
|
||||
var ListView = function ListView() {
|
||||
this.el = document.createElement("gaia-list");
|
||||
this.el.className = "install-list";
|
||||
|
||||
this.elements = Object.create(null);
|
||||
this.installHandlers = [];
|
||||
this.detailsHandlers = [];
|
||||
};
|
||||
|
||||
_extends(ListView, View);
|
||||
|
||||
ListView.prototype.update = function (list) {
|
||||
for (var manifestURL in list) {
|
||||
var data = list[manifestURL];
|
||||
if (!this.elements[manifestURL]) {
|
||||
this.elements[manifestURL] = this.addElement(data);
|
||||
}
|
||||
this.updateElement(this.elements[manifestURL], data);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.onInstall = function (handler) {
|
||||
if (this.installHandlers.indexOf(handler) === -1) {
|
||||
this.installHandlers.push(handler);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.offInstall = function (handler) {
|
||||
var index = this.installHandlers.indexOf(handler);
|
||||
if (index !== -1) {
|
||||
this.installHandlers.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.onDetails = function (handler) {
|
||||
if (this.detailsHandlers.indexOf(handler) === -1) {
|
||||
this.detailsHandlers.push(handler);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.offDetails = function (handler) {
|
||||
var index = this.detailsHandlers.indexOf(handler);
|
||||
if (index !== -1) {
|
||||
this.detailsHandlers.splice(index, 1);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.addElement = function (data) {
|
||||
var item = document.createElement("li");
|
||||
item.classList.add("item", data.type);
|
||||
item.innerHTML = this.listItemTemplate(data);
|
||||
IconHelper.setImage(item.querySelector(".icon"), data.icon);
|
||||
this.el.appendChild(item);
|
||||
|
||||
item.addEventListener("click", function (manifestURL, evt) {
|
||||
if (evt.target.classList.contains("install-button")) {
|
||||
return;
|
||||
}
|
||||
this.detailsHandlers.forEach(function (handler) {
|
||||
handler(manifestURL);
|
||||
});
|
||||
}.bind(this, data.manifestURL));
|
||||
|
||||
item.querySelector(".install-button").addEventListener("click", function (data) {
|
||||
this.installHandlers.forEach(function (handler) {
|
||||
handler(data);
|
||||
});
|
||||
}.bind(this, data));
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
ListView.prototype.updateElement = function (element, data) {
|
||||
element.classList.toggle("installed", data.installed);
|
||||
var button = element.querySelector(".install-button");
|
||||
button.textContent = data.installed ? "Open" : "Install";
|
||||
var icon = element.querySelector(".icon");
|
||||
if (data.icon && icon.src !== data.icon) {
|
||||
IconHelper.setImage(icon, data.icon);
|
||||
}
|
||||
};
|
||||
|
||||
ListView.prototype.activate = function () {
|
||||
this.el.classList.add("active");
|
||||
};
|
||||
|
||||
ListView.prototype.deactivate = function () {
|
||||
this.el.classList.remove("active");
|
||||
};
|
||||
|
||||
ListView.prototype.listItemTemplate = function (_ref) {
|
||||
var name = _ref.name;
|
||||
var author = _ref.author;
|
||||
var string = "\n <img class=\"icon\" />\n <div flex class=\"description\">\n <p class=\"name\">" + capitalize(name) + "</p>\n <p class=\"author\">" + author + "</p>\n </div>\n <span class=\"install-info\">Installed</span>\n <gaia-button class=\"install-button\">Loading...</gaia-button>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return ListView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = ListView;
|
||||
});
|
||||
64
gaia/distros/spark/apps/directory/js/view/main_view.js
Executable file
64
gaia/distros/spark/apps/directory/js/view/main_view.js
Executable file
|
|
@ -0,0 +1,64 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-header/dist/gaia-header", "components/gaia-dialog/gaia-dialog-alert", "components/fxos-dev-mode-dialog/fxos-dev-mode-dialog"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaHeaderDistGaiaHeader, _componentsGaiaDialogGaiaDialogAlert, _componentsFxosDevModeDialogFxosDevModeDialog) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var MainView = (function (View) {
|
||||
var MainView = function MainView(opts) {
|
||||
this.el = opts.el;
|
||||
this.uploadHandler = null;
|
||||
};
|
||||
|
||||
_extends(MainView, View);
|
||||
|
||||
MainView.prototype.render = function (isActivity) {
|
||||
var _this = this;
|
||||
View.prototype.render.call(this, [isActivity]);
|
||||
|
||||
if (isActivity) {
|
||||
this.el.querySelector("gaia-header").addEventListener("action", function (event) {
|
||||
if (event.detail.type === "back") {
|
||||
// Back from activity should close it via ActivityHelper.
|
||||
window.dispatchEvent(new CustomEvent("request-activity-finish"));
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var uploadBtn = document.getElementById("upload-link");
|
||||
if (!uploadBtn) {
|
||||
return;
|
||||
}
|
||||
uploadBtn.addEventListener("click", function () {
|
||||
if (_this.uploadHandler) {
|
||||
_this.uploadHandler();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
MainView.prototype.onUpload = function (handler) {
|
||||
this.uploadHandler = handler;
|
||||
};
|
||||
|
||||
MainView.prototype.template = function (isActivity) {
|
||||
var action = isActivity ? "action=\"back\"" : "";
|
||||
var upload = isActivity ? "" : "<button id=\"upload-link\"></button>";
|
||||
var string = "\n <gaia-header " + action + ">\n <h1>Hackerplace</h1>" + upload + "\n </gaia-header>\n <gaia-dialog-alert id=\"alert-dialog\">Placeholder</gaia-dialog-alert>\n <fxos-dev-mode-dialog></fxos-dev-mode-dialog>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return MainView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = MainView;
|
||||
});
|
||||
42
gaia/distros/spark/apps/directory/js/view/offline_view.js
Executable file
42
gaia/distros/spark/apps/directory/js/view/offline_view.js
Executable file
|
|
@ -0,0 +1,42 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-list/gaia-list"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaListGaiaList) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var OfflineView = (function (View) {
|
||||
var OfflineView = function OfflineView() {
|
||||
View.call(this);
|
||||
|
||||
this.el = document.createElement("gaia-list");
|
||||
this.el.id = "offline-container";
|
||||
};
|
||||
|
||||
_extends(OfflineView, View);
|
||||
|
||||
OfflineView.prototype.update = function (online) {
|
||||
// XXX: A bit gross. We should probably set this on the el only, but we had
|
||||
// issues with sibling selectors.
|
||||
document.body.classList.toggle("online", online);
|
||||
};
|
||||
|
||||
OfflineView.prototype.template = function () {
|
||||
var string = "<li flex>\n <i data-icon=\"exclamation\"></i>\n <p>You have no internet connection. Enable data or WiFi to refresh the\n app list.</p>\n </li>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return OfflineView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = OfflineView;
|
||||
});
|
||||
58
gaia/distros/spark/apps/directory/js/view/tabs_view.js
Executable file
58
gaia/distros/spark/apps/directory/js/view/tabs_view.js
Executable file
|
|
@ -0,0 +1,58 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-tabs/gaia-tabs"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaTabsGaiaTabs) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var TabsView = (function (View) {
|
||||
var TabsView = function TabsView() {
|
||||
this.el = document.createElement("div");
|
||||
this.el.id = "tabs-container";
|
||||
this.changeHandlers = [];
|
||||
this.tabList = ["apps", "addons"];
|
||||
};
|
||||
|
||||
_extends(TabsView, View);
|
||||
|
||||
TabsView.prototype.onTabChange = function (handler) {
|
||||
if (this.changeHandlers.indexOf(handler) === -1) {
|
||||
this.changeHandlers.push(handler);
|
||||
}
|
||||
};
|
||||
|
||||
TabsView.prototype.onChange = function (evt) {
|
||||
var selected = this.tabList[this.tabs.selected];
|
||||
this.changeHandlers.forEach(function (handler) {
|
||||
handler(selected);
|
||||
});
|
||||
};
|
||||
|
||||
TabsView.prototype.render = function (initialTab) {
|
||||
View.prototype.render.call(this, [this.tabList.indexOf(initialTab)]);
|
||||
// We can't create gaia-tabs with document.createElement
|
||||
// so we need to put gaia-tabs in template, and add event listeners
|
||||
// here, see https://github.com/gaia-components/gaia-tabs/issues/4
|
||||
this.tabs = this.el.querySelector("gaia-tabs");
|
||||
this.tabs.addEventListener("change", this.onChange.bind(this));
|
||||
};
|
||||
|
||||
TabsView.prototype.template = function (selected) {
|
||||
var string = "\n <gaia-tabs selected=\"" + selected + "\">\n <a>Apps</a>\n <a>Add-Ons</a>\n </gaia-tabs>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return TabsView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = TabsView;
|
||||
});
|
||||
218
gaia/distros/spark/apps/directory/js/view/upload_view.js
Executable file
218
gaia/distros/spark/apps/directory/js/view/upload_view.js
Executable file
|
|
@ -0,0 +1,218 @@
|
|||
define(["exports", "components/fxos-mvc/dist/mvc", "components/gaia-header/dist/gaia-header", "components/gaia-list/gaia-list", "gaia-icons", "components/gaia-text-input/gaia-text-input", "components/gaia-text-input/gaia-text-input-multiline", "js/lib/helpers", "js/model/list_model"], function (exports, _componentsFxosMvcDistMvc, _componentsGaiaHeaderDistGaiaHeader, _componentsGaiaListGaiaList, _gaiaIcons, _componentsGaiaTextInputGaiaTextInput, _componentsGaiaTextInputGaiaTextInputMultiline, _jsLibHelpers, _jsModelListModel) {
|
||||
"use strict";
|
||||
|
||||
var _extends = function (child, parent) {
|
||||
child.prototype = Object.create(parent.prototype, {
|
||||
constructor: {
|
||||
value: child,
|
||||
enumerable: false,
|
||||
writable: true,
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
child.__proto__ = parent;
|
||||
};
|
||||
|
||||
var View = _componentsFxosMvcDistMvc.View;
|
||||
var IconHelper = _jsLibHelpers.IconHelper;
|
||||
var ListModel = _jsModelListModel["default"];
|
||||
|
||||
|
||||
var UPLOAD_URL = "http://henretty.us/upload";
|
||||
|
||||
var UploadView = (function (View) {
|
||||
var UploadView = function UploadView() {
|
||||
this.el = document.createElement("div");
|
||||
this.el.id = "uploads";
|
||||
this.el.classList.add("popup");
|
||||
this.currentApp = null;
|
||||
|
||||
this.uploadBlacklist = ["app://ee50b34d-c8ce-b941-8020-5bc4693c770c/manifest.webapp", //FxStumbler
|
||||
"https://webmaker-app.mofostaging.net/manifest.webapp", "app://a9c7eb67-c2c8-8845-b150-5dd0a850200c/manifest.webapp", //Hackerplace
|
||||
"app://7a6c01c5-32fd-d041-9d0c-a70bb6c7c752/manifest.webapp", "app://customizer.gaiamobile.org/manifest.webapp", "app://default_theme.gaiamobile.org/manifest.webapp"];
|
||||
// Add current directory apps to upload blacklist.
|
||||
var directoryApps = (new ListModel()).getAppList();
|
||||
for (var manifestURL in directoryApps) {
|
||||
this.uploadBlacklist.push(manifestURL);
|
||||
}
|
||||
};
|
||||
|
||||
_extends(UploadView, View);
|
||||
|
||||
UploadView.prototype.render = function () {
|
||||
View.prototype.render.call(this);
|
||||
this.closeButton = this.$(".close");
|
||||
this.cancelButton = this.$("#upload-cancel");
|
||||
this.submitButton = this.$("#upload-submit");
|
||||
this.list = this.$("#upload-list");
|
||||
this.displayName = this.$("#display-name");
|
||||
this.displayIcon = this.$("#display-icon");
|
||||
this.nameInput = this.$("#upload-name");
|
||||
this.descriptionInput = this.$("#upload-description");
|
||||
this.alertDialog = document.body.querySelector("#alert-dialog");
|
||||
|
||||
this.closeButton.addEventListener("click", this.hide.bind(this));
|
||||
this.cancelButton.addEventListener("click", this.hideForm.bind(this));
|
||||
this.submitButton.addEventListener("click", this.upload.bind(this));
|
||||
this.createList();
|
||||
};
|
||||
|
||||
UploadView.prototype.showAlertDialog = function (msg) {
|
||||
this.alertDialog.textContent = msg;
|
||||
this.alertDialog.open();
|
||||
};
|
||||
|
||||
UploadView.prototype.isEligible = function (app) {
|
||||
if (this.uploadBlacklist.indexOf(app.manifestURL) !== -1) {
|
||||
return false;
|
||||
}
|
||||
// We don't support themes at the moment.
|
||||
if (app.manifest.role === "theme") {
|
||||
return false;
|
||||
}
|
||||
// All non-blacklisted add-ons are eligible.
|
||||
if (app.manifest.role === "addon") {
|
||||
return true;
|
||||
}
|
||||
// Only non-gaia non-marketplace apps are eligible for hackerplace.
|
||||
return (app.removable && app.installOrigin !== "https://marketplace.firefox.com");
|
||||
};
|
||||
|
||||
UploadView.prototype.createList = function () {
|
||||
var _this = this;
|
||||
var req;
|
||||
if (navigator.mozApps.mgmt) {
|
||||
req = navigator.mozApps.mgmt.getAll();
|
||||
} else {
|
||||
req = navigator.mozApps.getInstalled();
|
||||
}
|
||||
req.onsuccess = function () {
|
||||
var apps = req.result;
|
||||
var atLeastOneEligibleApp = false;
|
||||
apps.forEach(function (app) {
|
||||
if (_this.isEligible(app)) {
|
||||
atLeastOneEligibleApp = true;
|
||||
var item = document.createElement("li");
|
||||
var icon = _this.getIconUrl(app.manifest, app.origin);
|
||||
item.classList.add("item");
|
||||
item.innerHTML = _this.itemTemplate(app.manifest);
|
||||
IconHelper.setImage(item.querySelector(".icon"), icon);
|
||||
_this.list.appendChild(item);
|
||||
item.addEventListener("click", _this.showForm.bind(_this, app));
|
||||
}
|
||||
});
|
||||
|
||||
// Inform user if we did not find any uploadable apps.
|
||||
if (!atLeastOneEligibleApp) {
|
||||
var item = document.createElement("li");
|
||||
item.textContent = "No apps or addons to upload.";
|
||||
_this.list.appendChild(item);
|
||||
return;
|
||||
}
|
||||
};
|
||||
req.onerror = function (e) {
|
||||
console.log("Unable to fetch installed apps.", e);
|
||||
};
|
||||
};
|
||||
|
||||
UploadView.prototype.getIconUrl = function (manifest, origin) {
|
||||
if (!manifest || !manifest.icons) {
|
||||
return null;
|
||||
}
|
||||
var url;
|
||||
for (var size in manifest.icons) {
|
||||
url = manifest.icons[size];
|
||||
}
|
||||
// If we are given a relative path, we naively append app origin
|
||||
// to construct the full icon path.
|
||||
if (url.startsWith("/")) {
|
||||
url = origin + url;
|
||||
}
|
||||
return url;
|
||||
};
|
||||
|
||||
UploadView.prototype.showForm = function (app) {
|
||||
this.nameInput.value = app.manifest.developer && app.manifest.developer.name || "";
|
||||
this.descriptionInput.value = app.manifest.description || "";
|
||||
this.currentApp = app;
|
||||
this.displayName.textContent = app.manifest.name;
|
||||
IconHelper.setImage(this.displayIcon, this.getIconUrl(app.manifest, app.origin));
|
||||
this.el.classList.add("form");
|
||||
};
|
||||
|
||||
UploadView.prototype.hideForm = function (app) {
|
||||
this.nameInput.value = "";
|
||||
this.descriptionInput.value = "";
|
||||
this.currentApp = null;
|
||||
this.el.classList.remove("form");
|
||||
};
|
||||
|
||||
UploadView.prototype.show = function () {
|
||||
this.el.classList.add("active");
|
||||
};
|
||||
|
||||
UploadView.prototype.hide = function () {
|
||||
this.el.classList.remove("active");
|
||||
};
|
||||
|
||||
UploadView.prototype.upload = function () {
|
||||
var _this2 = this;
|
||||
if (!this.currentApp) {
|
||||
this.showAlertDialog("Error: current app not found");
|
||||
this.hideForm();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.nameInput.value === "") {
|
||||
this.showAlertDialog("You must fill out a name");
|
||||
return;
|
||||
}
|
||||
|
||||
this.currentApp["export"]().then(function (blob) {
|
||||
var name = encodeURIComponent(_this2.nameInput.value);
|
||||
var description = encodeURIComponent(_this2.descriptionInput.value);
|
||||
var url = "" + UPLOAD_URL + "?name=" + name + "&description=" + description;
|
||||
var ajax = new XMLHttpRequest();
|
||||
ajax.open("POST", url, true);
|
||||
ajax.onload = function () {
|
||||
console.log("Upload complete");
|
||||
};
|
||||
ajax.error = function (e) {
|
||||
_this2.showAlertDialog("App upload failed, " + e);
|
||||
console.log("Upload failed", e);
|
||||
};
|
||||
ajax.send(blob);
|
||||
_this2.showAlertDialog("Upload success! We will now review your app for the Hackerplace.");
|
||||
_this2.hideForm();
|
||||
}).then(function () {
|
||||
return window.dispatchEvent(new CustomEvent("achievement-rewarded", {
|
||||
detail: {
|
||||
criteria: "achievements/content-commander",
|
||||
evidence: "urn:fxos-directory:app:uploaded",
|
||||
name: "Content Commander",
|
||||
description: "Submit an app or add-on to Hackerplace",
|
||||
image: "./img/content-commander.png"
|
||||
}
|
||||
}));
|
||||
})["catch"](function (e) {
|
||||
_this2.showAlertDialog("Error exporting app");
|
||||
console.log("Error exporting app", e);
|
||||
});
|
||||
};
|
||||
|
||||
UploadView.prototype.itemTemplate = function (_ref) {
|
||||
var name = _ref.name;
|
||||
var string = "\n <img class=\"icon\" />\n <div flex class=\"description\">\n <p class=\"name\">" + name + "</p>\n </div>\n <i data-icon=\"forward\"></i>";
|
||||
return string;
|
||||
};
|
||||
|
||||
UploadView.prototype.template = function () {
|
||||
var string = "\n <gaia-header>\n <a class=\"close\"><i data-icon=\"close\"></i></a>\n <h1 id=\"upload-title\">Upload</h1>\n </gaia-header>\n <gaia-list id=\"upload-list\" class=\"install-list\"></gaia-list>\n <div id=\"upload-form\">\n <gaia-list class=\"info-list install-list\">\n <li class=\"item\">\n <img id=\"display-icon\" class=\"icon\" />\n <div flex class=\"description\">\n <p id=\"display-name\" class=\"name\"></p>\n </div>\n </li>\n </gaia-list>\n <div id=\"form-fields\">\n <label>Tell us your name <span class=\"red\">*</span></label>\n <gaia-text-input id=\"upload-name\"></gaia-text-input>\n <label>App Description (optional)</label>\n <gaia-text-input-multiline id=\"upload-description\">\n </gaia-text-input-multiline>\n <section id=\"upload-buttons\">\n <gaia-button id=\"upload-cancel\">Cancel</gaia-button>\n <gaia-button id=\"upload-submit\">Upload</gaia-button>\n </section>\n </div>\n </div>";
|
||||
return string;
|
||||
};
|
||||
|
||||
return UploadView;
|
||||
})(View);
|
||||
|
||||
exports["default"] = UploadView;
|
||||
});
|
||||
Loading…
Reference in a new issue