| Index: ui/file_manager/gallery/js/gallery.js
|
| diff --git a/ui/file_manager/gallery/js/gallery.js b/ui/file_manager/gallery/js/gallery.js
|
| index 570a9d7fab79e78baf93610713cd3d9ee0b8b0f5..fe0df3fd1538bcdf5cbe1305c57f252c9b02f0db 100644
|
| --- a/ui/file_manager/gallery/js/gallery.js
|
| +++ b/ui/file_manager/gallery/js/gallery.js
|
| @@ -20,12 +20,13 @@ ContentProvider.WORKER_SCRIPT = '/js/metadata_worker.js';
|
| /**
|
| * Data model for gallery.
|
| *
|
| + * @param {MetadataCache} metadataCache Metadata cache.
|
| * @constructor
|
| * @extends {cr.ui.ArrayDataModel}
|
| */
|
| -function GalleryDataModel() {
|
| +function GalleryDataModel(metadataCache) {
|
| cr.ui.ArrayDataModel.call(this, []);
|
| - this.metadataCache_ = null;
|
| + this.metadataCache_ = metadataCache;
|
| }
|
|
|
| /**
|
| @@ -49,40 +50,6 @@ GalleryDataModel.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.
|
| *
|
| * @param {Gallery.Item} item Original gallery item.
|
| @@ -223,7 +190,7 @@ function Gallery(volumeManager) {
|
| this.metadataCacheObserverId_ = null;
|
| this.onExternallyUnmountedBound_ = this.onExternallyUnmounted_.bind(this);
|
|
|
| - this.dataModel_ = new GalleryDataModel();
|
| + this.dataModel_ = new GalleryDataModel(this.context_.metadataCache);
|
| this.selectionModel_ = new cr.ui.ListSelectionModel();
|
|
|
| this.initDom_();
|
| @@ -436,50 +403,125 @@ Gallery.prototype.initToolbarButton_ = function(className, title) {
|
| * @param {!Array.<Entry>} selectedEntries Array of selected entries.
|
| */
|
| Gallery.prototype.load = function(entries, selectedEntries) {
|
| - this.dataModel_.initialize(this.metadataCache_, entries).then(function() {
|
| - // Apply selection.
|
| - this.selectionModel_.adjustLength(this.dataModel_.length);
|
| - var entryIndexesByURLs = {};
|
| - for (var index = 0; index < entries.length; index++) {
|
| - entryIndexesByURLs[entries[index].toURL()] = index;
|
| - }
|
| - for (var i = 0; i !== selectedEntries.length; i++) {
|
| - var selectedIndex = entryIndexesByURLs[selectedEntries[i].toURL()];
|
| - if (selectedIndex !== undefined)
|
| - this.selectionModel_.setIndexSelected(selectedIndex, true);
|
| - else
|
| - console.error('Cannot select ' + selectedEntries[i]);
|
| - }
|
| - if (this.selectionModel_.selectedIndexes.length === 0)
|
| - this.onSelection_();
|
| + // Obtains max chank size.
|
| + var maxChunkSize = 20;
|
| + var volumeInfo = this.volumeManager_.getVolumeInfo(entries[0]);
|
| + if (volumeInfo &&
|
| + volumeInfo.volumeType === VolumeManagerCommon.VolumeType.MTP) {
|
| + maxChunkSize = 1;
|
| + }
|
|
|
| - // Determine the initial mode.
|
| - var shouldShowMosaic = selectedEntries.length > 1 ||
|
| - (this.context_.pageState &&
|
| - this.context_.pageState.gallery === 'mosaic');
|
| - this.setCurrentMode_(shouldShowMosaic ? this.mosaicMode_ : this.slideMode_);
|
| + // 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++) {
|
| + var entry = selectedEntries[i];
|
| + entrySet[entry.toURL()] = {
|
| + 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
|
| + return a.index - b.index;
|
| + });
|
|
|
| - // Init mosaic mode.
|
| - var mosaic = this.mosaicMode_.getMosaic();
|
| - mosaic.init();
|
| -
|
| - // Do the initialization for each mode.
|
| - if (shouldShowMosaic) {
|
| - mosaic.show();
|
| - this.inactivityWatcher_.check(); // Show the toolbar.
|
| - cr.dispatchSimpleEvent(this, 'loaded');
|
| - } else {
|
| - this.slideMode_.enter(
|
| - null,
|
| - function() {
|
| - // Flash the toolbar briefly to show it is there.
|
| - this.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT);
|
| - }.bind(this),
|
| - function() {
|
| - cr.dispatchSimpleEvent(this, 'loaded');
|
| - }.bind(this));
|
| - }
|
| - }.bind(this)).catch(function(error) {
|
| + // 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 (selectionUpdated)
|
| + self.onSelection_();
|
| +
|
| + // Init modes after the first chunk is loaded.
|
| + if (firstChunk) {
|
| + // Determine the initial mode.
|
| + var shouldShowMosaic = selectedEntries.length > 1 ||
|
| + (self.context_.pageState &&
|
| + self.context_.pageState.gallery === 'mosaic');
|
| + self.setCurrentMode_(
|
| + shouldShowMosaic ? self.mosaicMode_ : self.slideMode_);
|
| +
|
| + // Init mosaic mode.
|
| + var mosaic = self.mosaicMode_.getMosaic();
|
| + mosaic.init();
|
| +
|
| + // Do the initialization for each mode.
|
| + if (shouldShowMosaic) {
|
| + mosaic.show();
|
| + self.inactivityWatcher_.check(); // Show the toolbar.
|
| + cr.dispatchSimpleEvent(self, 'loaded');
|
| + } else {
|
| + self.slideMode_.enter(
|
| + null,
|
| + function() {
|
| + // Flash the toolbar briefly to show it is there.
|
| + self.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT);
|
| + },
|
| + function() {
|
| + cr.dispatchSimpleEvent(self, 'loaded');
|
| + });
|
| + }
|
| + }
|
| +
|
| + // Continue to load chunks.
|
| + return loadChunk(/* firstChunk */ false);
|
| + });
|
| + };
|
| + loadChunk(/* firstChunk */ true).catch(function(error) {
|
| console.error(error.stack || error);
|
| });
|
| };
|
|
|