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:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

View 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;
});

View 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;
});

View 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;
});

View 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;
});

View 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;
});

View 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;
});

View 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;
});

View 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&nbsp;<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;
});