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
45
gaia/tv_apps/smart-settings/js/base.js
Executable file
45
gaia/tv_apps/smart-settings/js/base.js
Executable file
|
|
@ -0,0 +1,45 @@
|
|||
'use strict';
|
||||
/* global evt */
|
||||
|
||||
(function(exports) {
|
||||
function Base() {
|
||||
}
|
||||
|
||||
Base.prototype = new evt();
|
||||
|
||||
Base.prototype.bindSelf = function b_bindSelf() {
|
||||
for (var key in this) {
|
||||
if ((typeof this[key]) === 'function') {
|
||||
this[key] = this[key].bind(this);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Base.prototype.nodeListToArray = function b_nodeListToArray(obj) {
|
||||
return [].map.call(obj, function(element) {
|
||||
return element;
|
||||
});
|
||||
};
|
||||
|
||||
Base.prototype.simulateKeyEvent = function b_simulateKeyEvent(keyCode,
|
||||
charCode, ctrl, alt, shift, meta) {
|
||||
var evt = document.createEvent('KeyboardEvent');
|
||||
evt.initKeyEvent('keydown', true, true, null, ctrl || false, alt || false,
|
||||
shift || false, meta || false, keyCode, charCode || 0);
|
||||
window.dispatchEvent(evt);
|
||||
|
||||
evt = document.createEvent('KeyboardEvent');
|
||||
evt.initKeyEvent('keyup', true, true, null, ctrl || false, alt || false,
|
||||
shift || false, meta || false, keyCode, charCode || 0);
|
||||
window.dispatchEvent(evt);
|
||||
|
||||
evt = document.createEvent('KeyboardEvent');
|
||||
evt.initKeyEvent('keypress', true, true, null, ctrl || false, alt || false,
|
||||
shift || false, meta || false, keyCode, charCode || 0);
|
||||
window.dispatchEvent(evt);
|
||||
};
|
||||
|
||||
exports.Base = Base;
|
||||
|
||||
})(window);
|
||||
|
||||
128
gaia/tv_apps/smart-settings/js/option_menu.js
Executable file
128
gaia/tv_apps/smart-settings/js/option_menu.js
Executable file
|
|
@ -0,0 +1,128 @@
|
|||
'use strict';
|
||||
/* global Base, KeyEvent, SelectionBorder, SpatialNavigator */
|
||||
(function(exports) {
|
||||
|
||||
function OptionMenu() {
|
||||
this.bindSelf();
|
||||
this.menus = [];
|
||||
}
|
||||
|
||||
var proto = OptionMenu.prototype = new Base();
|
||||
|
||||
proto.addMenuItem = function om_addMenuItem(item) {
|
||||
this.menus.push(item);
|
||||
};
|
||||
|
||||
proto.removeMenuItem = function om_removeMenuItem(item) {
|
||||
var idx = this.menus.indexOf(item);
|
||||
if (idx < 0) {
|
||||
return;
|
||||
}
|
||||
// remove item from list.
|
||||
this.menus.splice(idx, 1);
|
||||
// remove UI from container
|
||||
var ui = this.container.querySelector('.menu-item[data-key="' +
|
||||
item.key + '"]');
|
||||
if (ui) {
|
||||
this.container.removeChild(ui);
|
||||
}
|
||||
};
|
||||
|
||||
proto.createMenu = function om_createMenu(item) {
|
||||
var self = this;
|
||||
var anchor = document.createElement('a');
|
||||
anchor.classList.add('menu-item');
|
||||
anchor.dataset.key = item.key;
|
||||
anchor.href = '#';
|
||||
anchor.addEventListener('click', function handleClick() {
|
||||
if (self.spatialNavigation.getFocusedElement() === anchor) {
|
||||
self.simulateKeyEvent(KeyEvent.DOM_VK_RETURN);
|
||||
} else {
|
||||
self.spatialNavigation.focus(anchor);
|
||||
}
|
||||
});
|
||||
var span = document.createElement('span');
|
||||
span.textContent = item.label;
|
||||
|
||||
if (item.selected) {
|
||||
anchor.classList.add('selected');
|
||||
}
|
||||
|
||||
anchor.appendChild(span);
|
||||
return anchor;
|
||||
};
|
||||
|
||||
proto.renderAt = function om_renderAt(container) {
|
||||
this.selectionBorder = new SelectionBorder({
|
||||
multiple: false,
|
||||
foreground: true,
|
||||
container: document.body
|
||||
});
|
||||
|
||||
this.container = container;
|
||||
var menuUIs = [];
|
||||
for(var i = 0; i < this.menus.length; i++) {
|
||||
menuUIs[i] = this.createMenu(this.menus[i]);
|
||||
if (this.menus[i].selected) {
|
||||
this.currentSelectedDOM = menuUIs[i];
|
||||
}
|
||||
container.appendChild(menuUIs[i]);
|
||||
}
|
||||
// init spatial navigation
|
||||
this.spatialNavigation = new SpatialNavigator(menuUIs);
|
||||
this.spatialNavigation.on('focus', this.handleChoosed);
|
||||
this.spatialNavigation.on('unfocus', this.handleUnchoosed);
|
||||
};
|
||||
|
||||
proto.handleChoosed = function om_handleChoosed(dom) {
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
this.selectionBorder.select(dom);
|
||||
dom.classList.add('focused');
|
||||
this.fire('itemChoosed', {
|
||||
'dom': dom
|
||||
});
|
||||
};
|
||||
|
||||
proto.handleUnchoosed = function om_handleUnchoosed(dom) {
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
dom.classList.remove('focused');
|
||||
this.selectionBorder.deselectAll();
|
||||
};
|
||||
|
||||
proto.move = function om_move(direction) {
|
||||
this.spatialNavigation.move(direction);
|
||||
};
|
||||
|
||||
proto.confirmSelection = function om_confirmSelection() {
|
||||
var dom = this.spatialNavigation.getFocusedElement();
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
var menu = this.menus.find(function(item) {
|
||||
return item.key === dom.dataset.key;
|
||||
});
|
||||
this.fire('itemConfirmed', menu);
|
||||
};
|
||||
|
||||
proto.stop = function om_stop() {
|
||||
this.container.innerHTML = '';
|
||||
this.menus = [];
|
||||
this.spatialNavigation.off('focus', this.handleChoosed);
|
||||
this.spatialNavigation.off('unfocus', this.handleUnchoosed);
|
||||
|
||||
this.selectionBorder.deselectAll();
|
||||
|
||||
delete this.spatialNavigation;
|
||||
delete this.selectionBorder;
|
||||
};
|
||||
|
||||
proto.start = function om_start() {
|
||||
this.spatialNavigation.focus(this.currentSelectedDOM);
|
||||
};
|
||||
|
||||
exports.OptionMenu = OptionMenu;
|
||||
})(window);
|
||||
238
gaia/tv_apps/smart-settings/js/settings.js
Executable file
238
gaia/tv_apps/smart-settings/js/settings.js
Executable file
|
|
@ -0,0 +1,238 @@
|
|||
'use strict';
|
||||
/* global Applications, Base, KeyEvent, Settings,
|
||||
SettingsGroup, SetupGroupList, SettingsList */
|
||||
|
||||
(function(exports) {
|
||||
|
||||
var mozSettings = window.navigator.mozSettings;
|
||||
|
||||
function $(id) {
|
||||
return document.getElementById(id);
|
||||
}
|
||||
|
||||
function Settings() {
|
||||
this.bindSelf();
|
||||
this.panels = {};
|
||||
this.settingsGroup = $('settings-group');
|
||||
this.settingsDetail = $('settings-detail');
|
||||
this.itemTitleElement = $('items-panel-title');
|
||||
}
|
||||
|
||||
var proto = Settings.prototype = new Base();
|
||||
|
||||
proto.groupClassMap = {
|
||||
'picture': SettingsList,
|
||||
'sound': SettingsList,
|
||||
'network': SettingsList,
|
||||
'timer': SettingsList,
|
||||
'setup': SetupGroupList,
|
||||
'help': SettingsList
|
||||
};
|
||||
|
||||
proto.init = function st_init() {
|
||||
Applications.init();
|
||||
var self = this;
|
||||
this.settingsGroup.addEventListener('transitionend',
|
||||
this.handleTransitionEnd);
|
||||
this.settingsDetail.addEventListener('transitionend',
|
||||
this.handleTransitionEnd);
|
||||
this.group = new SettingsGroup();
|
||||
// We don't need to bind again, because SettingsGroup had already auto bound
|
||||
// self.
|
||||
this.group.on('groupChoosed', this.switchGroup);
|
||||
this.group.init(this.settingsGroup, 'main-menu');
|
||||
window.addEventListener('keydown', this.handleKeyDown);
|
||||
document.body.dataset.active = 'group';
|
||||
this.group.on('ready', function groupReady() {
|
||||
self.group.setVisible(true);
|
||||
self.group.setActive(true);
|
||||
});
|
||||
};
|
||||
|
||||
proto.pumpMoveEvent = function st_pumpMoveEvent(key) {
|
||||
switch(document.body.dataset.active) {
|
||||
case 'list':
|
||||
this.activePanel.move(key);
|
||||
break;
|
||||
case 'option-menu':
|
||||
this.activeDetail.move(key);
|
||||
break;
|
||||
default:
|
||||
this.group.move(key);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.activateGroup = function st_activateGroup(group) {
|
||||
if (this.activePanel) {
|
||||
this.activePanel.setActive(false);
|
||||
}
|
||||
this.activePanel = this.panels[group];
|
||||
if (this.activePanel) {
|
||||
this.activePanel.setActive(true);
|
||||
}
|
||||
};
|
||||
|
||||
proto.changeState = function st_changeState(state) {
|
||||
this.transitionRunning = true;
|
||||
// we use dataset to keep the active state
|
||||
document.body.dataset.active = state;
|
||||
};
|
||||
|
||||
proto.confirmSelection = function st_confirmSelection(key) {
|
||||
if (this.transitionRunning) {
|
||||
// If transition is running, we don't need to accept any confirm or exit
|
||||
// command.
|
||||
return;
|
||||
}
|
||||
switch(document.body.dataset.active) {
|
||||
case 'group':
|
||||
this.changeState('list');
|
||||
document.body.dataset.activeGroup = this.selectedGroup;
|
||||
// set activate state to tell panel to show selection border.
|
||||
this.activateGroup(this.selectedGroup);
|
||||
break;
|
||||
case 'list':
|
||||
// Let active panel to handle the confirm command. The active panel may
|
||||
// use event to tell us to show other panels or enter other state.
|
||||
this.activePanel.confirmSelection(key);
|
||||
break;
|
||||
case 'option-menu':
|
||||
this.activeDetail.confirmSelection(key);
|
||||
this.changeState('list');
|
||||
this.activeDetail.stop();
|
||||
this.activeDetail = null;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.exitPanel = function st_exitPanel(key) {
|
||||
if (this.transitionRunning) {
|
||||
// If transition is running, we don't need to accept any confirm or exit
|
||||
// command.
|
||||
return;
|
||||
}
|
||||
switch(document.body.dataset.active) {
|
||||
case 'list':
|
||||
this.changeState('group');
|
||||
document.body.dataset.activeGroup = '';
|
||||
this.group.setActive(true);
|
||||
this.activateGroup(null);
|
||||
break;
|
||||
case 'option-menu':
|
||||
this.changeState('list');
|
||||
this.activeDetail.stop();
|
||||
this.activeDetail = null;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.handleTransitionEnd = function st_handleTransitionEnd(evt) {
|
||||
// We had transitions on few properties. So, we may receive multiple
|
||||
// transitionend events. But we should only use one, which is 'width', as
|
||||
// to be the ending of transition.
|
||||
if (evt.propertyName !== 'width') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.transitionRunning = false;
|
||||
switch(document.body.dataset.active) {
|
||||
case 'group':
|
||||
this.group.setActive(false);
|
||||
break;
|
||||
case 'list':
|
||||
this.group.setActive(false);
|
||||
this.activePanel.setActive(true);
|
||||
break;
|
||||
case 'option-menu':
|
||||
this.activePanel.setActive(false);
|
||||
this.activeDetail.start();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.handleItemChoosed = function st_handleItemChoosed(data) {
|
||||
if (data.type) {
|
||||
this.settingsDetail.dataset.type = data.type;
|
||||
} else {
|
||||
delete this.settingsDetail.dataset.type;
|
||||
}
|
||||
};
|
||||
|
||||
proto.handleKeyDown = function st_handleKeyDown(evt) {
|
||||
// XXX : It's better to use KeyEvent.Key and use "ArrowUp", "ArrowDown",
|
||||
// "ArrowLeft", "ArrowRight" for switching after Gecko synced with W3C
|
||||
// KeyboardEvent.Key standard. Here we still use KeyCode and customized
|
||||
// string of "up", "down", "left", "right" for the moment.
|
||||
var key = this.convertKeyToString(evt.keyCode);
|
||||
switch (key) {
|
||||
case 'up':
|
||||
case 'down':
|
||||
this.pumpMoveEvent(key);
|
||||
break;
|
||||
case 'enter':
|
||||
case 'right':
|
||||
this.confirmSelection(key);
|
||||
break;
|
||||
case 'esc':
|
||||
case 'left':
|
||||
this.exitPanel(key);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.convertKeyToString = function st_convertKeyToString(keyCode) {
|
||||
switch (keyCode) {
|
||||
case KeyEvent.DOM_VK_UP:
|
||||
return 'up';
|
||||
case KeyEvent.DOM_VK_RIGHT:
|
||||
return 'right';
|
||||
case KeyEvent.DOM_VK_DOWN:
|
||||
return 'down';
|
||||
case KeyEvent.DOM_VK_LEFT:
|
||||
return 'left';
|
||||
case KeyEvent.DOM_VK_RETURN:
|
||||
return 'enter';
|
||||
case KeyEvent.DOM_VK_BACK_SPACE:
|
||||
return 'esc';
|
||||
default:// we don't consume other keys.
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
proto.switchGroup = function st_switchGroup(id) {
|
||||
if (!this.panels[id]) {
|
||||
this.panels[id] = new this.groupClassMap[id]();
|
||||
this.panels[id].init($(id + '-section'));
|
||||
this.panels[id].on('itemChoosed', this.handleItemChoosed);
|
||||
this.panels[id].on('showOptionMenu', this.showOptionMenu);
|
||||
this.panels[id].on('updateSettings', this.updateSettings);
|
||||
}
|
||||
|
||||
for (var key in this.panels) {
|
||||
this.panels[key].setVisible(id === key);
|
||||
}
|
||||
this.selectedGroup = id;
|
||||
this.itemTitleElement.setAttribute('data-l10n-id', id);
|
||||
};
|
||||
|
||||
proto.showOptionMenu = function st_showOptionMenu(optionMenu) {
|
||||
if (this.transitionRunning) {
|
||||
// If transition is running, we don't need to accept any confirm or exit
|
||||
// command.
|
||||
return;
|
||||
}
|
||||
this.changeState('option-menu');
|
||||
optionMenu.renderAt($('option-menu-list'));
|
||||
this.activeDetail = optionMenu;
|
||||
};
|
||||
|
||||
proto.updateSettings = function st_updateSettings(data) {
|
||||
mozSettings.createLock().set(data);
|
||||
};
|
||||
|
||||
exports.Settings = Settings;
|
||||
}(window));
|
||||
|
||||
window.settings = new Settings();
|
||||
window.settings.init();
|
||||
27
gaia/tv_apps/smart-settings/js/settings_group.js
Executable file
27
gaia/tv_apps/smart-settings/js/settings_group.js
Executable file
|
|
@ -0,0 +1,27 @@
|
|||
'use strict';
|
||||
/* global SettingsList */
|
||||
(function(exports) {
|
||||
|
||||
function SettingsGroup() {
|
||||
var self = this;
|
||||
this.bindSelf();
|
||||
this.on('itemChoosed', function translateItemToGroup(data) {
|
||||
self.fire('groupChoosed', data.dom.dataset.group);
|
||||
});
|
||||
}
|
||||
|
||||
var proto = SettingsGroup.prototype = new SettingsList();
|
||||
|
||||
proto.setActive = function sg_setActive(active) {
|
||||
// no matter activate or not, we should reselect the dom node.
|
||||
this.selectionBorder.select(this.spatialNavigation.getFocusedElement());
|
||||
};
|
||||
|
||||
proto.init = function sg_init(dom, lazyDOMId) {
|
||||
this.container = dom;
|
||||
SettingsList.prototype.init.apply(this,
|
||||
[document.getElementById(lazyDOMId)]);
|
||||
};
|
||||
|
||||
exports.SettingsGroup = SettingsGroup;
|
||||
})(window);
|
||||
98
gaia/tv_apps/smart-settings/js/settings_list.js
Executable file
98
gaia/tv_apps/smart-settings/js/settings_list.js
Executable file
|
|
@ -0,0 +1,98 @@
|
|||
'use strict';
|
||||
/* global Base, KeyEvent, LazyLoader, SelectionBorder, SpatialNavigator */
|
||||
(function(exports) {
|
||||
|
||||
function SettingsList() {
|
||||
this.bindSelf();
|
||||
this.menuItems = {};
|
||||
}
|
||||
|
||||
var proto = SettingsList.prototype = new Base();
|
||||
|
||||
proto.init = function sl_init(dom) {
|
||||
var self = this;
|
||||
|
||||
this.panel = dom;
|
||||
this.selectionBorder = new SelectionBorder({
|
||||
multiple: false,
|
||||
foreground: true,
|
||||
container: document.body
|
||||
});
|
||||
|
||||
LazyLoader.load(dom, function lazyLoaded() {
|
||||
// select all menu items
|
||||
var items = self.panel.querySelectorAll('a.menu-item');
|
||||
var item = null;
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
item = items[i];
|
||||
item.addEventListener('click', self);
|
||||
self.menuItems[item.dataset.group] = item;
|
||||
}
|
||||
|
||||
// init spatial navigation
|
||||
self.spatialNavigation = new SpatialNavigator(
|
||||
self.nodeListToArray(items));
|
||||
self.spatialNavigation.on('focus', self.handleChoosed);
|
||||
self.spatialNavigation.on('unfocus', self.handleUnchoosed);
|
||||
self.spatialNavigation.focus();
|
||||
self.ready = true;
|
||||
self.fire('ready');
|
||||
});
|
||||
};
|
||||
|
||||
proto.handleEvent = function sl_handleEvent(evt) {
|
||||
switch(evt.type) {
|
||||
case 'click':
|
||||
if (this.spatialNavigation.getFocusedElement() === evt.currentTarget) {
|
||||
this.simulateKeyEvent(KeyEvent.DOM_VK_RETURN);
|
||||
} else {
|
||||
this.spatialNavigation.focus(evt.currentTarget);
|
||||
}
|
||||
evt.preventDefault();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.handleChoosed = function sl_handleChoosed(dom) {
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
this.selectionBorder.select(dom);
|
||||
dom.classList.add('focused');
|
||||
this.fire('itemChoosed', {
|
||||
'dom': dom
|
||||
});
|
||||
};
|
||||
|
||||
proto.handleUnchoosed = function sl_handleUnchoosed(dom) {
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
dom.classList.remove('focused');
|
||||
this.selectionBorder.deselectAll();
|
||||
};
|
||||
|
||||
proto.move = function sl_move(direction) {
|
||||
this.spatialNavigation.move(direction);
|
||||
};
|
||||
|
||||
proto.setVisible = function sl_setVisible(visible) {
|
||||
this.panel.hidden = !visible;
|
||||
if (!visible) {
|
||||
this.selectionBorder.deselectAll();
|
||||
}
|
||||
};
|
||||
|
||||
proto.setActive = function sl_setActive(active) {
|
||||
if (active && this.spatialNavigation.getFocusedElement()) {
|
||||
this.handleChoosed(this.spatialNavigation.getFocusedElement());
|
||||
} else if (document.body.dataset.active === 'group') {
|
||||
this.handleUnchoosed(this.spatialNavigation.getFocusedElement());
|
||||
} else {
|
||||
this.handleChoosed(this.spatialNavigation.getFocusedElement());
|
||||
}
|
||||
};
|
||||
|
||||
exports.SettingsList = SettingsList;
|
||||
})(window);
|
||||
|
||||
90
gaia/tv_apps/smart-settings/js/setup_group_list.js
Executable file
90
gaia/tv_apps/smart-settings/js/setup_group_list.js
Executable file
|
|
@ -0,0 +1,90 @@
|
|||
'use strict';
|
||||
/* global Applications, ManifestHelper, OptionMenu,
|
||||
SettingsCache, SettingsList */
|
||||
(function(exports) {
|
||||
|
||||
function SetupGroupList() {
|
||||
this.bindSelf();
|
||||
this.getSettings();
|
||||
}
|
||||
|
||||
var proto = SetupGroupList.prototype = new SettingsList();
|
||||
|
||||
proto.getSettings = function sgl_getSettings() {
|
||||
var self = this;
|
||||
SettingsCache.get('landing_app.manifestURL', function getDefault(val) {
|
||||
self.landingAppManifestURL = val;
|
||||
if (self.ready) {
|
||||
self.updateLandingAppText(val);
|
||||
} else {
|
||||
self.once('ready', self.updateLandingAppText.bind(self, val));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
proto.confirmSelection = function sgl_confirmSelection() {
|
||||
var dom = this.spatialNavigation.getFocusedElement();
|
||||
switch(dom.id) {
|
||||
case 'menu-item-landing-page':
|
||||
this.changeLandingPage();
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
proto.changeLandingPage = function sgl_changeLandingPage() {
|
||||
var self = this;
|
||||
var options = new OptionMenu();
|
||||
// We don't need to bind it again because it already binds itself.
|
||||
this.listDecks(this.landingAppManifestURL).forEach(options.addMenuItem);
|
||||
this.fire('showOptionMenu', options);
|
||||
options.on('itemConfirmed', function optionConfirmed(item) {
|
||||
self.landingAppManifestURL = item.key;
|
||||
self.updateLandingAppText(item.key);
|
||||
self.fire('updateSettings', {
|
||||
'landing_app.manifestURL': item.key
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
proto.updateLandingAppText = function sgl_updateValueUI(manifestURL) {
|
||||
var span = this.panel.querySelector('#menu-item-landing-page > span');
|
||||
span.dataset.value = Applications.getName(manifestURL, '');
|
||||
};
|
||||
|
||||
proto.handleChoosed = function sgl_handleChoosed(dom) {
|
||||
if (!dom) {
|
||||
return;
|
||||
}
|
||||
this.selectionBorder.select(dom);
|
||||
dom.classList.add('focused');
|
||||
|
||||
var eventData = {
|
||||
'dom': dom
|
||||
};
|
||||
switch(dom.id) {
|
||||
case 'menu-item-landing-page':
|
||||
eventData.type = 'option-menu';
|
||||
break;
|
||||
}
|
||||
|
||||
this.fire('itemChoosed', eventData);
|
||||
};
|
||||
|
||||
proto.listDecks = function sg_listDecks(current) {
|
||||
var decks = Applications.listAppsByRole();
|
||||
var deckItems = [];
|
||||
|
||||
for (var i = 0; i < decks.length; i++) {
|
||||
var manifest = new ManifestHelper(decks[i].app.manifest);
|
||||
deckItems[deckItems.length] = {
|
||||
key: decks[i].manifestURL,
|
||||
label: manifest.name,
|
||||
selected: (decks[i].manifestURL === current)
|
||||
};
|
||||
}
|
||||
|
||||
return deckItems;
|
||||
};
|
||||
|
||||
exports.SetupGroupList = SetupGroupList;
|
||||
})(window);
|
||||
Loading…
Reference in a new issue