Commit 828afd22 authored by hirono@chromium.org's avatar hirono@chromium.org

Gallery: Load gallery items by chunk on startup.

BUG=chrome-os-partner:28087
TEST=run on link

Review URL: https://codereview.chromium.org/470983002

Cr-Commit-Position: refs/heads/master@{#289922}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289922 0039d316-1c4b-4281-b951-d872f2087c98
parent 662d0d63
...@@ -20,12 +20,13 @@ ContentProvider.WORKER_SCRIPT = '/js/metadata_worker.js'; ...@@ -20,12 +20,13 @@ ContentProvider.WORKER_SCRIPT = '/js/metadata_worker.js';
/** /**
* Data model for gallery. * Data model for gallery.
* *
* @param {MetadataCache} metadataCache Metadata cache.
* @constructor * @constructor
* @extends {cr.ui.ArrayDataModel} * @extends {cr.ui.ArrayDataModel}
*/ */
function GalleryDataModel() { function GalleryDataModel(metadataCache) {
cr.ui.ArrayDataModel.call(this, []); cr.ui.ArrayDataModel.call(this, []);
this.metadataCache_ = null; this.metadataCache_ = metadataCache;
} }
/** /**
...@@ -48,40 +49,6 @@ GalleryDataModel.prototype = { ...@@ -48,40 +49,6 @@ GalleryDataModel.prototype = {
__proto__: cr.ui.ArrayDataModel.prototype __proto__: cr.ui.ArrayDataModel.prototype
}; };
/**
* Initializes the data model.
*
* @param {MetadataCache} metadataCache Metadata cache.
* @param {Array.<FileEntry>} entries Image entries.
* @return {Promise} Promise to be fulfilled with after initialization.
*/
GalleryDataModel.prototype.initialize = function(metadataCache, entries) {
// Store metadata cache.
this.metadataCache_ = metadataCache;
// Obtain metadata.
var metadataPromise = new Promise(function(fulfill) {
this.metadataCache_.get(entries, Gallery.METADATA_TYPE, fulfill);
}.bind(this));
// Initialize the gallery by using the metadata.
return metadataPromise.then(function(metadata) {
// Check the length of metadata.
if (entries.length !== metadata.length)
return Promise.reject('Failed to obtain metadata for the entries.');
// Obtains items.
var items = entries.map(function(entry, i) {
var clonedMetadata = MetadataCache.cloneMetadata(metadata[i]);
return new Gallery.Item(
entry, clonedMetadata, metadataCache, /* original */ true);
});
// Update the models.
this.push.apply(this, items);
}.bind(this));
};
/** /**
* Saves new image. * Saves new image.
* *
...@@ -223,7 +190,7 @@ function Gallery(volumeManager) { ...@@ -223,7 +190,7 @@ function Gallery(volumeManager) {
this.metadataCacheObserverId_ = null; this.metadataCacheObserverId_ = null;
this.onExternallyUnmountedBound_ = this.onExternallyUnmounted_.bind(this); this.onExternallyUnmountedBound_ = this.onExternallyUnmounted_.bind(this);
this.dataModel_ = new GalleryDataModel(); this.dataModel_ = new GalleryDataModel(this.context_.metadataCache);
this.selectionModel_ = new cr.ui.ListSelectionModel(); this.selectionModel_ = new cr.ui.ListSelectionModel();
this.initDom_(); this.initDom_();
...@@ -436,50 +403,125 @@ Gallery.prototype.initToolbarButton_ = function(className, title) { ...@@ -436,50 +403,125 @@ Gallery.prototype.initToolbarButton_ = function(className, title) {
* @param {!Array.<Entry>} selectedEntries Array of selected entries. * @param {!Array.<Entry>} selectedEntries Array of selected entries.
*/ */
Gallery.prototype.load = function(entries, selectedEntries) { Gallery.prototype.load = function(entries, selectedEntries) {
this.dataModel_.initialize(this.metadataCache_, entries).then(function() { // Obtains max chank size.
// Apply selection. var maxChunkSize = 20;
this.selectionModel_.adjustLength(this.dataModel_.length); var volumeInfo = this.volumeManager_.getVolumeInfo(entries[0]);
var entryIndexesByURLs = {}; if (volumeInfo &&
for (var index = 0; index < entries.length; index++) { volumeInfo.volumeType === VolumeManagerCommon.VolumeType.MTP) {
entryIndexesByURLs[entries[index].toURL()] = index; maxChunkSize = 1;
}
// Make loading list.
var entrySet = {};
for (var i = 0; i < entries.length; i++) {
var entry = entries[i];
entrySet[entry.toURL()] = {
entry: entry,
selected: false,
index: i
};
} }
for (var i = 0; i !== selectedEntries.length; i++) { for (var i = 0; i < selectedEntries.length; i++) {
var selectedIndex = entryIndexesByURLs[selectedEntries[i].toURL()]; var entry = selectedEntries[i];
if (selectedIndex !== undefined) entrySet[entry.toURL()] = {
this.selectionModel_.setIndexSelected(selectedIndex, true); entry: entry,
selected: true,
index: i
};
}
var loadingList = [];
for (var url in entrySet) {
loadingList.push(entrySet[url]);
}
loadingList = loadingList.sort(function(a, b) {
if (a.selected && !b.selected)
return -1;
else if (!a.selected && b.selected)
return 1;
else else
console.error('Cannot select ' + selectedEntries[i]); return a.index - b.index;
});
// Load entries.
// Use the self variable capture-by-closure because it is faster than bind.
var self = this;
var loadChunk = function(firstChunk) {
// Extract chunk.
var chunk = loadingList.splice(0, maxChunkSize);
if (!chunk.length)
return;
return new Promise(function(fulfill) {
// Obtains metadata for chunk.
var entries = chunk.map(function(chunkItem) {
return chunkItem.entry;
});
self.metadataCache_.get(entries, Gallery.METADATA_TYPE, fulfill);
}).then(function(metadataList) {
if (chunk.length !== metadataList.length)
return Promise.reject('Failed to load metadata.');
// Add items to the model.
var items = chunk.map(function(chunkItem, index) {
var clonedMetadata = MetadataCache.cloneMetadata(metadataList[index]);
return new Gallery.Item(
chunkItem.entry,
clonedMetadata,
self.metadataCache_,
/* original */ true);
});
self.dataModel_.push.apply(self.dataModel_, items);
// Apply the selection.
var selectionUpdated = false;
for (var i = 0; i < chunk.length; i++) {
if (!chunk[i].selected)
continue;
var index = self.dataModel_.indexOf(items[i]);
if (index < 0)
continue;
self.selectionModel_.setIndexSelected(index);
selectionUpdated = true;
} }
if (this.selectionModel_.selectedIndexes.length === 0) if (selectionUpdated)
this.onSelection_(); self.onSelection_();
// Init modes after the first chunk is loaded.
if (firstChunk) {
// Determine the initial mode. // Determine the initial mode.
var shouldShowMosaic = selectedEntries.length > 1 || var shouldShowMosaic = selectedEntries.length > 1 ||
(this.context_.pageState && (self.context_.pageState &&
this.context_.pageState.gallery === 'mosaic'); self.context_.pageState.gallery === 'mosaic');
this.setCurrentMode_(shouldShowMosaic ? this.mosaicMode_ : this.slideMode_); self.setCurrentMode_(
shouldShowMosaic ? self.mosaicMode_ : self.slideMode_);
// Init mosaic mode. // Init mosaic mode.
var mosaic = this.mosaicMode_.getMosaic(); var mosaic = self.mosaicMode_.getMosaic();
mosaic.init(); mosaic.init();
// Do the initialization for each mode. // Do the initialization for each mode.
if (shouldShowMosaic) { if (shouldShowMosaic) {
mosaic.show(); mosaic.show();
this.inactivityWatcher_.check(); // Show the toolbar. self.inactivityWatcher_.check(); // Show the toolbar.
cr.dispatchSimpleEvent(this, 'loaded'); cr.dispatchSimpleEvent(self, 'loaded');
} else { } else {
this.slideMode_.enter( self.slideMode_.enter(
null, null,
function() { function() {
// Flash the toolbar briefly to show it is there. // Flash the toolbar briefly to show it is there.
this.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT); self.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT);
}.bind(this), },
function() { function() {
cr.dispatchSimpleEvent(this, 'loaded'); cr.dispatchSimpleEvent(self, 'loaded');
}.bind(this)); });
} }
}.bind(this)).catch(function(error) { }
// Continue to load chunks.
return loadChunk(/* firstChunk */ false);
});
};
loadChunk(/* firstChunk */ true).catch(function(error) {
console.error(error.stack || error); console.error(error.stack || error);
}); });
}; };
......
...@@ -437,6 +437,7 @@ Mosaic.prototype.onSplice_ = function(event) { ...@@ -437,6 +437,7 @@ Mosaic.prototype.onSplice_ = function(event) {
this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles)); this.tiles_.splice.apply(this.tiles_, [index, 0].concat(newTiles));
this.initTiles_(newTiles); this.initTiles_(newTiles);
this.scheduleLayout(Mosaic.LAYOUT_DELAY);
} }
if (this.tiles_.length !== this.dataModel_.length) if (this.tiles_.length !== this.dataModel_.length)
...@@ -776,7 +777,7 @@ Mosaic.Layout.prototype.getHeight = function() { ...@@ -776,7 +777,7 @@ Mosaic.Layout.prototype.getHeight = function() {
*/ */
Mosaic.Layout.prototype.getTiles = function() { Mosaic.Layout.prototype.getTiles = function() {
return Array.prototype.concat.apply([], return Array.prototype.concat.apply([],
this.columns_.map(function(c) { return c.getTiles() })); this.columns_.map(function(c) { return c.getTiles(); }));
}; };
/** /**
...@@ -852,8 +853,8 @@ Mosaic.Layout.prototype.add = function(tile, isLast) { ...@@ -852,8 +853,8 @@ Mosaic.Layout.prototype.add = function(tile, isLast) {
this.columns_.push(this.newColumn_); this.columns_.push(this.newColumn_);
this.newColumn_ = null; this.newColumn_ = null;
if (this.mode_ === Mosaic.Layout.MODE_FINAL) { if (this.mode_ === Mosaic.Layout.MODE_FINAL && isFinalColumn) {
this.getLastColumn_().layout(); this.commit_();
continue; continue;
} }
...@@ -893,8 +894,6 @@ Mosaic.Layout.prototype.add = function(tile, isLast) { ...@@ -893,8 +894,6 @@ Mosaic.Layout.prototype.add = function(tile, isLast) {
* @private * @private
*/ */
Mosaic.Layout.prototype.commit_ = function(opt_offsetX, opt_offsetY) { Mosaic.Layout.prototype.commit_ = function(opt_offsetX, opt_offsetY) {
console.assert(this.mode_ !== Mosaic.Layout.MODE_FINAL,
'Did not expect final layout');
for (var i = 0; i !== this.columns_.length; i++) { for (var i = 0; i !== this.columns_.length; i++) {
this.columns_[i].layout(opt_offsetX, opt_offsetY); this.columns_[i].layout(opt_offsetX, opt_offsetY);
} }
...@@ -925,7 +924,7 @@ Mosaic.Layout.prototype.findHorizontalLayout_ = function() { ...@@ -925,7 +924,7 @@ Mosaic.Layout.prototype.findHorizontalLayout_ = function() {
if (tiles.length === 1) if (tiles.length === 1)
return null; // Single tile layout is always the same. return null; // Single tile layout is always the same.
var tileHeights = tiles.map(function(t) { return t.getMaxContentHeight() }); var tileHeights = tiles.map(function(t) { return t.getMaxContentHeight(); });
var minTileHeight = Math.min.apply(null, tileHeights); var minTileHeight = Math.min.apply(null, tileHeights);
for (var h = minTileHeight; h < this.viewportHeight_; h += minTileHeight) { for (var h = minTileHeight; h < this.viewportHeight_; h += minTileHeight) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment