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
311
gaia/apps/gallery/js/startup.js
Executable file
311
gaia/apps/gallery/js/startup.js
Executable file
|
|
@ -0,0 +1,311 @@
|
|||
/* global LazyLoader, Pick, Thumbnails, $, thumbnails */
|
||||
/* global MediaDB, photodb, picking, setView, LAYOUT_MODE, currentView */
|
||||
/* global Overlay, isPhone, doNotScanInBackgroundHack, fullscreenButtons */
|
||||
/* global launchCameraApp, deleteSelectedItems, shareSelectedItems */
|
||||
/* global resizeHandler, currentFrame, showFile, fileCreated, fileDeleted */
|
||||
/* global files, thumbnailClickHandler, exitEdit */
|
||||
|
||||
(function startup() {
|
||||
'use strict';
|
||||
|
||||
var firstScanDone = false; // Have we completed our first scan yet?
|
||||
|
||||
showUI(); // We're localized, so unhide
|
||||
registerEventHandlers(); // Hook up UI elements
|
||||
finishDBInitialization(); // Finish MediaDB initialization
|
||||
setInitialView(); // Start off in thumbnail list mode
|
||||
registerActivityHandler(); // Handle pick and browse activities
|
||||
displayThumbnails(); // Get the thumbnails displayed
|
||||
doNotScanInBackgroundHack(photodb); // Remove as part of bug 1046995
|
||||
|
||||
function showUI() {
|
||||
// <body> children are hidden until the UI is translated
|
||||
document.body.classList.remove('hidden');
|
||||
|
||||
// load frame_script.js for preview mode and show loading background
|
||||
if (!isPhone) {
|
||||
LazyLoader.load('js/frame_scripts.js');
|
||||
}
|
||||
|
||||
// Tell performance monitors that our chrome is visible
|
||||
window.performance.mark('navigationLoaded');
|
||||
}
|
||||
|
||||
function registerEventHandlers() {
|
||||
// Clicking on the select button goes to thumbnail select mode
|
||||
$('thumbnails-select-button').onclick =
|
||||
setView.bind(null, LAYOUT_MODE.select);
|
||||
|
||||
// Clicking on the cancel button goes from thumbnail select mode
|
||||
// back to thumbnail list mode
|
||||
$('selected-header').addEventListener('action',
|
||||
setView.bind(null, LAYOUT_MODE.list));
|
||||
|
||||
if (!isPhone) {
|
||||
$('fullscreen-toolbar-header').addEventListener('action', function() {
|
||||
setView(LAYOUT_MODE.list);
|
||||
});
|
||||
}
|
||||
|
||||
// The camera buttons should launch the camera app
|
||||
fullscreenButtons.camera.onclick = launchCameraApp;
|
||||
|
||||
$('thumbnails-camera-button').onclick = launchCameraApp;
|
||||
Overlay.addEventListener('camera', launchCameraApp);
|
||||
|
||||
// Clicking on the delete button in thumbnail select mode deletes all
|
||||
// selected items
|
||||
$('thumbnails-delete-button').onclick = deleteSelectedItems;
|
||||
|
||||
// Clicking on the share button in select mode shares all selected images
|
||||
$('thumbnails-share-button').onclick = shareSelectedItems;
|
||||
|
||||
Overlay.addEventListener('cancel', function() {
|
||||
if (picking) {
|
||||
Pick.cancel();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle resize events
|
||||
window.onresize = resizeHandler;
|
||||
|
||||
// All our buttons and UI elements are hooked up, so we've reached
|
||||
// the "interactive" mark.
|
||||
window.performance.mark('navigationInteractive');
|
||||
}
|
||||
|
||||
// We created the MediaDB in thumbnails.js. Now we need to finish
|
||||
// setting it up.
|
||||
function finishDBInitialization() {
|
||||
|
||||
// Display a dialog if the DB needs to upgrade before becoming ready
|
||||
photodb.onupgrading = function(evt) {
|
||||
Overlay.show('upgrade');
|
||||
};
|
||||
|
||||
// This is called when DeviceStorage becomes unavailable because the
|
||||
// sd card is removed or because it is mounted for USB mass storage
|
||||
// This may be called before onready if it is unavailable to begin with
|
||||
// We don't need one of these handlers for the video db, since both
|
||||
// will get the same event at more or less the same time.
|
||||
photodb.onunavailable = function() {
|
||||
// Switch back to the thumbnail view unless it is a pick activity.
|
||||
// If we were viewing or editing an image it might not be there
|
||||
// anymore when the MediaDB becomes available again.
|
||||
if (!picking) {
|
||||
// If we are editing image, call exitEdit to revoke blob URLs
|
||||
// and close the editor object. This is a known case where the
|
||||
// user can lose their work. See Bug 1148347
|
||||
if (currentView === LAYOUT_MODE.edit) {
|
||||
exitEdit();
|
||||
}
|
||||
setView(LAYOUT_MODE.list);
|
||||
} else {
|
||||
Pick.restart();
|
||||
}
|
||||
|
||||
// If storage becomes unavailble (e.g. the user starts a USB Mass Storage
|
||||
// Lock the user out of the app, and tell them why
|
||||
var why = photodb.state;
|
||||
if (why === MediaDB.NOCARD) {
|
||||
Overlay.show('nocard');
|
||||
}
|
||||
else if (why === MediaDB.UNMOUNTED) {
|
||||
Overlay.show('pluggedin');
|
||||
}
|
||||
};
|
||||
|
||||
photodb.onready = function() {
|
||||
// Hide the nocard or pluggedin overlay if it is displayed
|
||||
if (Overlay.current === 'nocard' || Overlay.current === 'pluggedin' ||
|
||||
Overlay.current === 'upgrade') {
|
||||
Overlay.hide();
|
||||
}
|
||||
|
||||
// We also scan the file system for new files every time we get
|
||||
// a ready event. That code is in a different event handler that
|
||||
// is not registered until we are notified the Thumbnails.created
|
||||
// promise resolves.
|
||||
};
|
||||
|
||||
photodb.onscanstart = function onscanstart() {
|
||||
// Prevents user to edit images when scanning pictures from storage
|
||||
fullscreenButtons.edit.classList.add('disabled');
|
||||
// Show the scanning indicator
|
||||
$('throbber').classList.remove('hidden');
|
||||
$('throbber').classList.add('throb');
|
||||
};
|
||||
|
||||
photodb.onscanend = function onscanend() {
|
||||
// Allows the user to edit images when scanning is finished
|
||||
fullscreenButtons.edit.classList.remove('disabled');
|
||||
|
||||
if (Overlay.current === 'scanning') {
|
||||
Overlay.show('emptygallery');
|
||||
}
|
||||
else if (!isPhone && !currentFrame.displayingImage &&
|
||||
!currentFrame.displayingVideo) {
|
||||
// focus on latest one if client hasn't clicked any of
|
||||
// them
|
||||
showFile(0);
|
||||
}
|
||||
|
||||
// Hide the scanning indicator
|
||||
// setTimeout() is to workaround Bug 1166500
|
||||
$('throbber').classList.remove('throb');
|
||||
setTimeout(function() { $('throbber').classList.add('hidden'); }, 100);
|
||||
|
||||
// If this was the first scan after startup, then tell
|
||||
// performance monitors that the app is finally fully loaded and stable.
|
||||
if (!firstScanDone) {
|
||||
firstScanDone = true;
|
||||
window.performance.mark('fullyLoaded');
|
||||
}
|
||||
};
|
||||
|
||||
// On devices with internal and external device storage, this handler is
|
||||
// triggered when the user removes the sdcard. MediaDB remains usable
|
||||
// and we'll get a bunch of deleted events for the files that are no longer
|
||||
// available. But we need to listen to this event so we can switch back
|
||||
// to the list of thumbnails. We don't want to be left viewing or editing
|
||||
// a photo that is no longer available.
|
||||
photodb.oncardremoved = function oncardremoved() {
|
||||
// If the user pulls the sdcard while trying to pick an image, give up
|
||||
if (picking) {
|
||||
Pick.cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
setView(LAYOUT_MODE.list);
|
||||
};
|
||||
|
||||
// One or more files was created (or was just discovered by a scan)
|
||||
photodb.oncreated = function(event) {
|
||||
event.detail.forEach(fileCreated);
|
||||
};
|
||||
|
||||
// One or more files were deleted (or were just discovered missing)
|
||||
photodb.ondeleted = function(event) {
|
||||
event.detail.forEach(fileDeleted);
|
||||
};
|
||||
|
||||
// If the mediadb is not still in its initial OPENING state then we
|
||||
// missed a "ready" or "unavailable" or "upgrading" event, and need
|
||||
// to call the appropriate handler now. Note that we don't start scanning
|
||||
// until after the ready event arrives and we enumerate the db, so it
|
||||
// is not possible for us to miss a scanstart or scanend events. And if
|
||||
// we miss a created or deleted event, the relevant files will be found
|
||||
// during the enumeration, so this is all we have to look for now
|
||||
switch (photodb.state) {
|
||||
case MediaDB.UPGRADING:
|
||||
photodb.onupgrading();
|
||||
break;
|
||||
case MediaDB.READY:
|
||||
photodb.onready();
|
||||
break;
|
||||
case MediaDB.NOCARD:
|
||||
case MediaDB.UNMOUNTED:
|
||||
photodb.onunavailable();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function setInitialView() {
|
||||
// Start off in thumbnail list mode or in pick mode
|
||||
if (picking) {
|
||||
setView(LAYOUT_MODE.pick);
|
||||
}
|
||||
else {
|
||||
setView(LAYOUT_MODE.list);
|
||||
}
|
||||
}
|
||||
|
||||
// Register a handler for pick and browse activities
|
||||
function registerActivityHandler() {
|
||||
navigator.mozSetMessageHandler('activity', function activityHandler(a) {
|
||||
var activityName = a.source.name;
|
||||
switch (activityName) {
|
||||
case 'browse':
|
||||
// The user is probably coming to us from the camera, and she probably
|
||||
// wants to see the list of thumbnails. If the gallery was already
|
||||
// running when the browse activity was started, then we might not be
|
||||
// displaying the thumbnails. If we're currently displaying a single
|
||||
// image, switch to the thumbnails. But if the user left the gallery
|
||||
// in the middle of an edit or in the middle of making a selection,
|
||||
// then returning to the thumbnail list would cause her to lose work,
|
||||
// so in those cases we don't change anything and let the gallery
|
||||
// resume where the user left it. See Bug 846220.
|
||||
if (currentView === LAYOUT_MODE.fullscreen) {
|
||||
setView(LAYOUT_MODE.list);
|
||||
}
|
||||
break;
|
||||
case 'pick':
|
||||
LazyLoader.load('js/pick.js', function() { Pick.start(a); });
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Get the thumbnails displayed
|
||||
function displayThumbnails() {
|
||||
// thumbnails.js started created thumbanils offscreen.
|
||||
// We're ready now to deal with them
|
||||
|
||||
// Copy stuff to global variables
|
||||
// jshint ignore:start
|
||||
thumbnails = Thumbnails.container; // The element that holds the thumbnail
|
||||
thumbnailList = Thumbnails.list; // The object that represents them
|
||||
// jshint ignore:end
|
||||
|
||||
// Now insert the thumbnails into the document.
|
||||
var placeholder = $('thumbnails-placeholder');
|
||||
placeholder.parentElement.replaceChild(thumbnails, placeholder);
|
||||
|
||||
// Handle clicks on the thumbnails
|
||||
thumbnails.addEventListener('click', thumbnailClickHandler);
|
||||
|
||||
// When the first page of thumbnails is diplayed, we can emit
|
||||
// our 'visually complete' mark for startup time comparison
|
||||
Thumbnails.firstpage.then(function() {
|
||||
// Tell performance monitors that "above the fold" content is displayed
|
||||
// and is ready to interact with.
|
||||
window.performance.mark('visuallyLoaded');
|
||||
window.performance.mark('contentInteractive');
|
||||
|
||||
// Remove the attribute to trigger gaia header font-fit logic, defer it
|
||||
// til now to postpone the overhead. Add setTimeout to lazyload
|
||||
// gaia-header.js aynchronously.
|
||||
setTimeout(function() {
|
||||
LazyLoader.load(['shared/elements/gaia-header/dist/gaia-header.js'],
|
||||
function() {
|
||||
var headers = document.querySelectorAll('gaia-header');
|
||||
for (var i = 0; i < headers.length; ++i) {
|
||||
headers[i].removeAttribute('no-font-fit');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// When all the thumbnails have been created, we can start a scan
|
||||
Thumbnails.complete.then(function() {
|
||||
if (files.length === 0) { // If we didn't find anything
|
||||
Overlay.show('scanning');
|
||||
}
|
||||
|
||||
// Send a custom mark to performance monitors to note that we're done
|
||||
// enumerating the database at this point. We won't send the final
|
||||
// fullyLoaded marker until we're completely stable and have
|
||||
// finished scanning.
|
||||
window.performance.mark('mediaEnumerated');
|
||||
|
||||
// Now that we've enumerated all the photos and videos we already know
|
||||
// about it is time to go and scan the filesystem for new ones. If the
|
||||
// MediaDB is fully ready, we can scan now. Either way, we always want
|
||||
// to scan every time we get a new 'ready' event.
|
||||
photodb.addEventListener('ready', function() { photodb.scan(); });
|
||||
if (photodb.state === MediaDB.READY) { // if already ready then scan now
|
||||
photodb.scan();
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
Loading…
Reference in a new issue