diff options
-rw-r--r-- | ui/file_manager/file_manager/foreground/js/directory_contents.js | 47 | ||||
-rw-r--r-- | ui/file_manager/file_manager/foreground/js/directory_model.js | 114 |
2 files changed, 139 insertions, 22 deletions
diff --git a/ui/file_manager/file_manager/foreground/js/directory_contents.js b/ui/file_manager/file_manager/foreground/js/directory_contents.js index 10ca762..c1b0f2b 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_contents.js +++ b/ui/file_manager/file_manager/foreground/js/directory_contents.js @@ -663,6 +663,53 @@ DirectoryContents.prototype.scan = function(refresh) { }; /** + * Adds/removes/updates items of file list. + * @param {Array.<Entry>} updatedEntries Entries of updated/added files. + * @param {Array.<string>} removedUrls URLs of removed files. + */ +DirectoryContents.prototype.update = function(updatedEntries, removedUrls) { + var removedMap = {}; + for (var i = 0; i < removedUrls.length; i++) { + removedMap[removedUrls[i]] = true; + } + + var updatedMap = {}; + for (var i = 0; i < updatedEntries.length; i++) { + updatedMap[updatedEntries[i].toURL()] = updatedEntries[i]; + } + + var updatedList = []; + for (var i = 0; i < this.fileList_.length; i++) { + var url = this.fileList_.item(i).toURL(); + + if (url in removedMap) { + this.fileList_.splice(i, 1); + i--; + continue; + } + + if (url in updatedMap) { + updatedList.push(updatedMap[url]); + delete updatedMap[url]; + } + } + + var addedList = []; + for (var url in updatedMap) { + addedList.push(updatedMap[url]); + } + + if (removedUrls.length > 0) + this.fileList_.metadataCache_.clearByUrl(removedUrls, '*'); + + this.prefetchMetadata(updatedList, true, function() { + this.onNewEntries_(true, addedList); + this.onScanFinished_(); + this.onScanCompleted_(); + }.bind(this)); +}; + +/** * Cancels the running scan. */ DirectoryContents.prototype.cancelScan = function() { diff --git a/ui/file_manager/file_manager/foreground/js/directory_model.js b/ui/file_manager/file_manager/foreground/js/directory_model.js index 23230b3..36c5abe 100644 --- a/ui/file_manager/file_manager/foreground/js/directory_model.js +++ b/ui/file_manager/file_manager/foreground/js/directory_model.js @@ -171,21 +171,21 @@ DirectoryModel.prototype.onWatcherDirectoryChanged_ = function(event) { var directoryEntry = this.getCurrentDirEntry(); if (event.changedFiles) { - var urls = event.changedFiles.map(function(change) { return change.url; }); - util.URLsToEntries(urls).then(function(result) { - // Removes the metadata of invalid entries. - if (result.failureUrls.length > 0) - this.metadataCache_.clearByUrl(result.failureUrls, '*'); - - // Rescans after force-refreshing the metadata of the changed entries. - var entries = result.entries; - if (entries.length) { - this.currentDirContents_.prefetchMetadata(entries, true, function() { - this.rescanSoon(false); - }.bind(this)); - } else { - this.rescanSoon(false); - } + var addedOrUpdatedFileUrls = []; + var deletedFileUrls = []; + event.changedFiles.forEach(function(change) { + if (change.changes.length === 1 && change.changes[0] === 'delete') + deletedFileUrls.push(change.url); + else + addedOrUpdatedFileUrls.push(change.url); + }); + + util.URLsToEntries(addedOrUpdatedFileUrls).then(function(result) { + deletedFileUrls = deletedFileUrls.concat(result.failureUrls); + + // Passing the resolved entries and failed URLs as the removed files. + // The URLs are removed files and they chan't be resolved. + this.partialUpdate_(result.entries, deletedFileUrls); }.bind(this)).catch(function(error) { console.error('Error in proceeding the changed event.', error, 'Fallback to force-refresh'); @@ -446,6 +446,64 @@ DirectoryModel.prototype.clearAndScan_ = function(newDirContents, }; /** + * Adds/removes/updates items of file list. + * @param {Array.<Entry>} updatedEntries Entries of updated/added files. + * @param {Array.<string>} removedUrls URLs of removed files. + * @private + */ +DirectoryModel.prototype.partialUpdate_ = + function(changedEntries, removedUrls) { + // This update should be included in the current running update. + if (this.pendingScan_) + return; + + if (this.runningScan_) { + // Do update after the current scan is finished. + var previousScan = this.runningScan_; + var onPreviousScanCompleted = function() { + previousScan.removeEventListener('scan-completed', + onPreviousScanCompleted); + // Run the update asynchronously. + Promise.resolve().then(function() { + if (!this.runningScan_) + this.partialUpdate_(changedEntries, removedUrls); + }.bind(this)); + }.bind(this); + previousScan.addEventListener('scan-completed', onPreviousScanCompleted); + return; + } + + var onFinish = function() { + this.runningScan_ = null; + + this.currentDirContents_.removeEventListener( + 'scan-completed', onCompleted); + this.currentDirContents_.removeEventListener('scan-failed', onFailure); + this.currentDirContents_.removeEventListener( + 'scan-cancelled', onCancelled); + }.bind(this); + + var onCompleted = function() { + onFinish(); + cr.dispatchSimpleEvent(this, 'rescan-completed'); + }.bind(this); + + var onFailure = function() { + onFinish(); + }; + + var onCancelled = function() { + onFinish(); + }; + + this.runningScan_ = this.currentDirContents_; + this.currentDirContents_.addEventListener('scan-completed', onCompleted); + this.currentDirContents_.addEventListener('scan-failed', onFailure); + this.currentDirContents_.addEventListener('scan-cancelled', onCancelled); + this.currentDirContents_.update(changedEntries, removedUrls); +}; + +/** * Perform a directory contents scan. Should be called only from rescan() and * clearAndScan_(). * @@ -480,7 +538,16 @@ DirectoryModel.prototype.scan_ = function( return false; }.bind(this); + var onFinished = function() { + dirContents.removeEventListener('scan-completed', onSuccess); + dirContents.removeEventListener('scan-updated', updatedCallback); + dirContents.removeEventListener('scan-failed', onFailure); + dirContents.removeEventListener('scan-cancelled', cancelledCallback); + }; + var onSuccess = function() { + onFinished(); + // Record metric for Downloads directory. if (!dirContents.isSearch()) { var locationInfo = @@ -500,6 +567,8 @@ DirectoryModel.prototype.scan_ = function( }.bind(this); var onFailure = function() { + onFinished(); + this.runningScan_ = null; this.scanFailures_++; failureCallback(); @@ -511,12 +580,17 @@ DirectoryModel.prototype.scan_ = function( this.rescanLater(refresh); }.bind(this); + var onCancelled = function() { + onFinished(); + cancelledCallback(); + }; + this.runningScan_ = dirContents; dirContents.addEventListener('scan-completed', onSuccess); dirContents.addEventListener('scan-updated', updatedCallback); dirContents.addEventListener('scan-failed', onFailure); - dirContents.addEventListener('scan-cancelled', cancelledCallback); + dirContents.addEventListener('scan-cancelled', onCancelled); dirContents.scan(refresh); }; @@ -595,7 +669,7 @@ DirectoryModel.prototype.onEntriesChanged = function(kind, entries) { entriesToAdd.push(entries[i]); } } - this.getFileList().push.apply(this.getFileList(), entriesToAdd); + this.partialUpdate_(entriesToAdd, []); }.bind(this)).catch(function(error) { console.error(error.stack || error); }); @@ -603,11 +677,7 @@ DirectoryModel.prototype.onEntriesChanged = function(kind, entries) { case util.EntryChangedKind.DELETED: // This is the delete event. - for (var i = 0; i < entries.length; i++) { - var index = this.findIndexByEntry_(entries[i]); - if (index >= 0) - this.getFileList().splice(index, 1); - } + this.partialUpdate_([], util.entriesToURLs(entries)); break; default: |