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
272
gaia/apps/homescreen/js/pages.js
Executable file
272
gaia/apps/homescreen/js/pages.js
Executable file
|
|
@ -0,0 +1,272 @@
|
|||
/* global PagesStore, IconsHelper */
|
||||
'use strict';
|
||||
|
||||
(function(exports) {
|
||||
|
||||
/**
|
||||
* The size in pixels of the icons in the pinned pages.
|
||||
*/
|
||||
const PAGES_ICON_SIZE = 30;
|
||||
|
||||
function Pages() {
|
||||
// Element references
|
||||
this.panel = document.getElementById('pages-panel');
|
||||
this.panels = document.getElementById('panels');
|
||||
this.pages = document.getElementById('pages');
|
||||
this.scrollable = document.querySelector('#pages-panel > .scrollable');
|
||||
this.bottombar = document.getElementById('bottombar');
|
||||
this.remove = document.getElementById('remove');
|
||||
this.done = document.getElementById('done');
|
||||
|
||||
// Tracking if the list is empty
|
||||
this.empty = true;
|
||||
|
||||
// Edit mode
|
||||
this.editMode = false;
|
||||
|
||||
// Dialogs
|
||||
this.dialogs = [];
|
||||
|
||||
// Signal handlers
|
||||
this.pages.addEventListener('click', this);
|
||||
this.pages.addEventListener('contextmenu', this);
|
||||
this.pages.addEventListener('keydown', this);
|
||||
window.addEventListener('resize', this);
|
||||
|
||||
this.done.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
this.exitEditMode();
|
||||
});
|
||||
|
||||
this.remove.addEventListener('click', e => {
|
||||
e.preventDefault();
|
||||
this.unpinSelectedCard();
|
||||
});
|
||||
|
||||
// Initialise and populate pinned pages
|
||||
this.pagesStore = new PagesStore('places');
|
||||
this.pagesStore.init().then(() => {
|
||||
// Triggered when pages are added and updated.
|
||||
document.addEventListener('places-set', (e) => {
|
||||
var id = e.detail.id;
|
||||
this.pagesStore.get(id).then((page) => {
|
||||
for (var child of this.pages.children) {
|
||||
if (child.dataset.id === id) {
|
||||
if (!page.data.pinned) {
|
||||
this.removeCard(child);
|
||||
} else {
|
||||
this.updatePinnedPage(child, page.data);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!page.data.pinned) {
|
||||
return;
|
||||
}
|
||||
|
||||
// A new page was pinned.
|
||||
this.addPinnedPage(page.data);
|
||||
});
|
||||
});
|
||||
|
||||
document.addEventListener('places-removed', (e) => {
|
||||
var id = e.detail.id;
|
||||
for (var child of this.pages.children) {
|
||||
if (child.dataset.id === id) {
|
||||
this.removeCard(child);
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('places-cleared', () => {
|
||||
this.exitEditMode();
|
||||
|
||||
for (var child of this.pages.children) {
|
||||
this.pages.removeChild(child);
|
||||
}
|
||||
|
||||
if (!this.empty) {
|
||||
this.empty = true;
|
||||
this.panel.classList.add('empty');
|
||||
}
|
||||
});
|
||||
},
|
||||
(e) => {
|
||||
console.error('Error initialising pinned pages', e);
|
||||
}).then(() => {
|
||||
return this.pagesStore.getAll().then((pages) => {
|
||||
for (var page of pages) {
|
||||
this.addPinnedPage(page.data);
|
||||
}
|
||||
|
||||
// If there are no pinned pages, display helpful information.
|
||||
if (this.empty) {
|
||||
this.panel.classList.add('empty');
|
||||
}
|
||||
}, (e) => {
|
||||
console.error('Error getting pinned pages', e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Pages.prototype = {
|
||||
updatePinnedPage: function(card, page) {
|
||||
card.title = page.title;
|
||||
card.dataset.id = page.url;
|
||||
card.style.order = -Math.round(page.pinTime / 1000);
|
||||
page.meta = page.meta || {};
|
||||
|
||||
if (page.screenshot) {
|
||||
page.meta.screenshot = page.screenshot;
|
||||
}
|
||||
|
||||
setTimeout(function(card, page) {
|
||||
card.meta = page.meta;
|
||||
IconsHelper.getIconBlob(page.url, PAGES_ICON_SIZE, page)
|
||||
.then((iconObj) => {
|
||||
if (iconObj.blob) {
|
||||
var iconURL = URL.createObjectURL(iconObj.blob);
|
||||
card.icon = `url(${iconURL})`;
|
||||
}
|
||||
})
|
||||
.catch((e) => {
|
||||
console.error('Failed to fetch icon', e);
|
||||
});
|
||||
}.bind(this, card, page));
|
||||
},
|
||||
|
||||
addPinnedPage: function(page) {
|
||||
var pinCard = document.createElement('gaia-pin-card');
|
||||
|
||||
// Make the card accessible/allow activation
|
||||
pinCard.tabIndex = 0;
|
||||
pinCard.setAttribute('role', 'link');
|
||||
|
||||
this.updatePinnedPage(pinCard, page);
|
||||
this.pages.appendChild(pinCard);
|
||||
|
||||
if (this.empty) {
|
||||
this.empty = false;
|
||||
this.panel.classList.remove('empty');
|
||||
}
|
||||
},
|
||||
|
||||
launchCard: function(card) {
|
||||
var features = {
|
||||
name: card.title,
|
||||
icon: card.icon,
|
||||
remote: true
|
||||
};
|
||||
|
||||
window.open(card.dataset.id, '_blank', Object.keys(features).map(
|
||||
key => encodeURIComponent(key) + '=' + encodeURIComponent(features[key])
|
||||
).join(','));
|
||||
},
|
||||
|
||||
enterEditMode: function(card) {
|
||||
if (this.selectedCard) {
|
||||
this.selectedCard.classList.remove('selected');
|
||||
}
|
||||
if (card) {
|
||||
this.selectedCard = card;
|
||||
card.classList.add('selected');
|
||||
}
|
||||
|
||||
this.editMode = true;
|
||||
document.body.classList.add('edit-mode');
|
||||
this.remove.classList.add('active');
|
||||
},
|
||||
|
||||
exitEditMode: function() {
|
||||
if (!this.editMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.editMode = false;
|
||||
document.body.classList.remove('edit-mode');
|
||||
this.remove.classList.remove('active');
|
||||
if (this.selectedCard) {
|
||||
this.selectedCard.classList.remove('selected');
|
||||
this.selectedCard = null;
|
||||
}
|
||||
},
|
||||
|
||||
removeCard: function(card) {
|
||||
if (this.selectedCard === card) {
|
||||
this.selectedCard = null;
|
||||
}
|
||||
this.pages.removeChild(card, () => {
|
||||
if (!this.empty && this.pages.children.length === 0) {
|
||||
this.exitEditMode();
|
||||
this.empty = true;
|
||||
this.panel.classList.add('empty');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
unpinSelectedCard: function() {
|
||||
if (!this.selectedCard) {
|
||||
return;
|
||||
}
|
||||
|
||||
var id = this.selectedCard.dataset.id;
|
||||
|
||||
// Remove child immediately, datastore operations can be quite slow
|
||||
this.removeCard(this.selectedCard);
|
||||
|
||||
this.pagesStore.get(id).then(entry => {
|
||||
entry.data.pinned = false;
|
||||
this.pagesStore.datastore.put(entry.data, id).then(() => {},
|
||||
e => {
|
||||
console.error('Error unpinning page:', e);
|
||||
});
|
||||
}, e => {
|
||||
console.error('Error retrieving page to unpin:', e);
|
||||
});
|
||||
},
|
||||
|
||||
handleEvent: function(e) {
|
||||
switch (e.type) {
|
||||
case 'click':
|
||||
if (e.target.nodeName !== 'GAIA-PIN-CARD') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (this.editMode) {
|
||||
this.enterEditMode(e.target);
|
||||
} else {
|
||||
this.launchCard(e.target);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'contextmenu':
|
||||
if (e.target.nodeName !== 'GAIA-PIN-CARD') {
|
||||
break;
|
||||
}
|
||||
this.enterEditMode(e.target);
|
||||
break;
|
||||
|
||||
case 'keydown':
|
||||
if (e.target.nodeName !== 'GAIA-PIN-CARD') {
|
||||
break;
|
||||
}
|
||||
|
||||
switch (e.keyCode) {
|
||||
case 32: // Space
|
||||
case 13: // Enter
|
||||
this.launchCard(e.target);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'resize':
|
||||
this.pages.synchronise();
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.Pages = Pages;
|
||||
|
||||
}(window));
|
||||
Loading…
Reference in a new issue