| Index: chrome/browser/resources/file_manager/js/photo/photo_import.js
|
| diff --git a/chrome/browser/resources/file_manager/js/photo/photo_import.js b/chrome/browser/resources/file_manager/js/photo/photo_import.js
|
| deleted file mode 100644
|
| index 346e13c01788b8dedd4c980d703ad0c35339ffcc..0000000000000000000000000000000000000000
|
| --- a/chrome/browser/resources/file_manager/js/photo/photo_import.js
|
| +++ /dev/null
|
| @@ -1,582 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -'use strict';
|
| -
|
| -document.addEventListener('DOMContentLoaded', function() {
|
| - PhotoImport.load();
|
| -});
|
| -
|
| -/**
|
| - * The main Photo App object.
|
| - * @param {HTMLElement} dom Container.
|
| - * @param {VolumeManagerWrapper} volumeManager The initialized
|
| - * VolumeManagerWrapper instance.
|
| - * @param {Object} params Parameters.
|
| - * @constructor
|
| - */
|
| -function PhotoImport(dom, volumeManager, params) {
|
| - this.dom_ = dom;
|
| - this.document_ = this.dom_.ownerDocument;
|
| - this.metadataCache_ = params.metadataCache;
|
| - this.volumeManager_ = volumeManager;
|
| - this.fileOperationManager_ = FileOperationManagerWrapper.getInstance();
|
| - this.mediaFilesList_ = null;
|
| - this.destination_ = null;
|
| - this.myPhotosDirectory_ = null;
|
| - this.parentWindowId_ = params.parentWindowId;
|
| -
|
| - this.initDom_();
|
| - this.initMyPhotos_();
|
| - this.loadSource_(params.source);
|
| -}
|
| -
|
| -PhotoImport.prototype = { __proto__: cr.EventTarget.prototype };
|
| -
|
| -/**
|
| - * Single item width.
|
| - * Keep in sync with .grid-item rule in photo_import.css.
|
| - */
|
| -PhotoImport.ITEM_WIDTH = 164 + 8;
|
| -
|
| -/**
|
| - * Number of tries in creating a destination directory.
|
| - */
|
| -PhotoImport.CREATE_DESTINATION_TRIES = 100;
|
| -
|
| -/**
|
| - * Loads app in the document body.
|
| - * @param {Object=} opt_params Parameters.
|
| - */
|
| -PhotoImport.load = function(opt_params) {
|
| - ImageUtil.metrics = metrics;
|
| -
|
| - var hash = location.hash ? location.hash.substr(1) : '';
|
| - var query = location.search ? location.search.substr(1) : '';
|
| - var params = opt_params || {};
|
| - if (!params.source) params.source = hash;
|
| - if (!params.parentWindowId && query) params.parentWindowId = query;
|
| - if (!params.metadataCache) params.metadataCache = MetadataCache.createFull();
|
| -
|
| - var api = chrome.fileBrowserPrivate || window.top.chrome.fileBrowserPrivate;
|
| - api.getStrings(function(strings) {
|
| - loadTimeData.data = strings;
|
| - var dom = document.querySelector('.photo-import');
|
| -
|
| - var volumeManager = new VolumeManagerWrapper(
|
| - VolumeManagerWrapper.DriveEnabledStatus.DRIVE_ENABLED);
|
| - volumeManager.ensureInitialized(function() {
|
| - new PhotoImport(dom, volumeManager, params);
|
| - });
|
| - });
|
| -};
|
| -
|
| -/**
|
| - * One-time initialization of dom elements.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.initDom_ = function() {
|
| - this.dom_.setAttribute('loading', '');
|
| - this.dom_.ownerDocument.defaultView.addEventListener(
|
| - 'resize', this.onResize_.bind(this));
|
| -
|
| - this.spinner_ = this.dom_.querySelector('.spinner');
|
| -
|
| - this.document_.querySelector('title').textContent =
|
| - loadTimeData.getString('PHOTO_IMPORT_TITLE');
|
| - this.dom_.querySelector('.caption').textContent =
|
| - loadTimeData.getString('PHOTO_IMPORT_CAPTION');
|
| - this.selectAllNone_ = this.dom_.querySelector('.select');
|
| - this.selectAllNone_.addEventListener('click',
|
| - this.onSelectAllNone_.bind(this));
|
| -
|
| - this.dom_.querySelector('label[for=delete-after-checkbox]').textContent =
|
| - loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER');
|
| - this.selectedCount_ = this.dom_.querySelector('.selected-count');
|
| -
|
| - this.importButton_ = this.dom_.querySelector('button.import');
|
| - this.importButton_.textContent =
|
| - loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON');
|
| - this.importButton_.addEventListener('click', this.onImportClick_.bind(this));
|
| -
|
| - this.cancelButton_ = this.dom_.querySelector('button.cancel');
|
| - this.cancelButton_.textContent = str('CANCEL_LABEL');
|
| - this.cancelButton_.addEventListener('click', this.onCancelClick_.bind(this));
|
| -
|
| - this.grid_ = this.dom_.querySelector('grid');
|
| - cr.ui.Grid.decorate(this.grid_);
|
| - this.grid_.itemConstructor = GridItem.bind(null, this);
|
| - this.fileList_ = new cr.ui.ArrayDataModel([]);
|
| - this.grid_.selectionModel = new cr.ui.ListSelectionModel();
|
| - this.grid_.dataModel = this.fileList_;
|
| - this.grid_.selectionModel.addEventListener('change',
|
| - this.onSelectionChanged_.bind(this));
|
| - this.onSelectionChanged_();
|
| -
|
| - this.importingDialog_ = new ImportingDialog(
|
| - this.dom_, this.fileOperationManager_,
|
| - this.metadataCache_, this.parentWindowId_);
|
| -
|
| - var dialogs = cr.ui.dialogs;
|
| - dialogs.BaseDialog.OK_LABEL = str('OK_LABEL');
|
| - dialogs.BaseDialog.CANCEL_LABEL = str('CANCEL_LABEL');
|
| - this.alert_ = new dialogs.AlertDialog(this.dom_);
|
| -};
|
| -
|
| -/**
|
| - * One-time initialization of the My Photos directory.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.initMyPhotos_ = function() {
|
| - var driveVolume = this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE);
|
| - if (!driveVolume || driveVolume.error || !driveVolume.root) {
|
| - this.onError_(loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));
|
| - return;
|
| - }
|
| -
|
| - util.getOrCreateDirectory(
|
| - driveVolume.root,
|
| - loadTimeData.getString('PHOTO_IMPORT_MY_PHOTOS_DIRECTORY_NAME'),
|
| - function(entry) {
|
| - // This may enable the import button, so check that.
|
| - this.myPhotosDirectory_ = entry;
|
| - this.onSelectionChanged_();
|
| - },
|
| - function(error) {
|
| - this.onError_(loadTimeData.getString('PHOTO_IMPORT_DRIVE_ERROR'));
|
| - }.bind(this));
|
| -};
|
| -
|
| -/**
|
| - * Creates the destination directory.
|
| - * @param {function} onSuccess Callback on success.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.createDestination_ = function(onSuccess) {
|
| - var onError = this.onError_.bind(
|
| - this, loadTimeData.getString('PHOTO_IMPORT_DESTINATION_ERROR'));
|
| -
|
| - var dateFormatter = Intl.DateTimeFormat(
|
| - [] /* default locale */,
|
| - {year: 'numeric', month: 'short', day: 'numeric'});
|
| -
|
| - var baseName = PathUtil.join(
|
| - RootDirectory.DRIVE,
|
| - loadTimeData.getString('PHOTO_IMPORT_MY_PHOTOS_DIRECTORY_NAME'),
|
| - dateFormatter.format(new Date()));
|
| -
|
| - var driveVolume = this.volumeManager_.getVolumeInfo(RootDirectory.DRIVE);
|
| - if (!driveVolume || driveVolume.error || !driveVolume.root) {
|
| - onError();
|
| - return;
|
| - }
|
| -
|
| - var tryNext = function(number) {
|
| - if (number > PhotoImport.CREATE_DESTINATION_TRIES) {
|
| - console.error('Too many directories with the same base name exist.');
|
| - onError();
|
| - return;
|
| - }
|
| -
|
| - var directoryName = baseName;
|
| - if (number > 1)
|
| - directoryName += ' (' + (tryNumber) + ')';
|
| - driveVolume.root.getDirectory(
|
| - directoryName,
|
| - {create: true, exclusive: true},
|
| - function(entry) {
|
| - this.destination_ = entry;
|
| - onSuccess();
|
| - }.bind(this),
|
| - function(error) {
|
| - if (error.code === FileError.PATH_EXISTS_ERR) {
|
| - // If there already exists an entry, retry with incrementing the
|
| - // number.
|
| - tryNext(number + 1);
|
| - return;
|
| - }
|
| - onError();
|
| - }.bind(this));
|
| - }.bind(this);
|
| -
|
| - tryNext(1);
|
| -};
|
| -
|
| -
|
| -/**
|
| - * Load the source contents.
|
| - * @param {string} source Path to source.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.loadSource_ = function(source) {
|
| - var onError = this.onError_.bind(
|
| - this, loadTimeData.getString('PHOTO_IMPORT_SOURCE_ERROR'));
|
| -
|
| - var result = [];
|
| - this.volumeManager_.resolvePath(
|
| - source,
|
| - function(sourceEntry) {
|
| - util.traverseTree(
|
| - entry,
|
| - function(entry) {
|
| - if (!FileType.isVisible(entry))
|
| - return false;
|
| - if (FileType.isImageOrVideo(entry))
|
| - result.push(entry);
|
| - return true;
|
| - },
|
| - function() {
|
| - this.dom_.removeAttribute('loading');
|
| - this.mediaFilesList_ = result;
|
| - this.fillGrid_();
|
| - }.bind(this),
|
| - onError);
|
| - }.bind(this),
|
| - onError);
|
| -};
|
| -
|
| -/**
|
| - * Renders files into grid.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.fillGrid_ = function() {
|
| - if (!this.mediaFilesList_) return;
|
| - this.fileList_.splice(0, this.fileList_.length);
|
| - this.fileList_.push.apply(this.fileList_, this.mediaFilesList_);
|
| -};
|
| -
|
| -/**
|
| - * Creates groups for files based on modification date.
|
| - * @param {Array.<Entry>} files File list.
|
| - * @param {Object} filesystem Filesystem metadata.
|
| - * @return {Array.<Object>} List of grouped items.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.createGroups_ = function(files, filesystem) {
|
| - var dateFormatter = Intl.DateTimeFormat(
|
| - [] /* default locale */,
|
| - {year: 'numeric', month: 'short', day: 'numeric'});
|
| -
|
| - var columns = this.grid_.columns;
|
| -
|
| - var unknownGroup = {
|
| - type: 'group',
|
| - date: 0,
|
| - title: loadTimeData.getString('PHOTO_IMPORT_UNKNOWN_DATE'),
|
| - items: []
|
| - };
|
| -
|
| - var groupsMap = {};
|
| -
|
| - for (var index = 0; index < files.length; index++) {
|
| - var props = filesystem[index];
|
| - var item = { type: 'entry', entry: files[index] };
|
| -
|
| - if (!props || !props.modificationTime) {
|
| - item.group = unknownGroup;
|
| - unknownGroup.items.push(item);
|
| - continue;
|
| - }
|
| -
|
| - var date = new Date(props.modificationTime);
|
| - date.setHours(0);
|
| - date.setMinutes(0);
|
| - date.setSeconds(0);
|
| - date.setMilliseconds(0);
|
| -
|
| - var time = date.getTime();
|
| - if (!(time in groupsMap)) {
|
| - groupsMap[time] = {
|
| - type: 'group',
|
| - date: date,
|
| - title: dateFormatter.format(date),
|
| - items: []
|
| - };
|
| - }
|
| -
|
| - var group = groupsMap[time];
|
| - group.items.push(item);
|
| - item.group = group;
|
| - }
|
| -
|
| - var groups = [];
|
| - for (var time in groupsMap) {
|
| - if (groupsMap.hasOwnProperty(time)) {
|
| - groups.push(groupsMap[time]);
|
| - }
|
| - }
|
| - if (unknownGroup.items.length > 0)
|
| - groups.push(unknownGroup);
|
| -
|
| - groups.sort(function(a, b) {
|
| - return b.date.getTime() - a.date.getTime();
|
| - });
|
| -
|
| - var list = [];
|
| - for (var index = 0; index < groups.length; index++) {
|
| - var group = groups[index];
|
| -
|
| - list.push(group);
|
| - for (var t = 1; t < columns; t++) {
|
| - list.push({ type: 'empty' });
|
| - }
|
| -
|
| - for (var j = 0; j < group.items.length; j++) {
|
| - list.push(group.items[j]);
|
| - }
|
| -
|
| - var count = group.items.length;
|
| - while (count % columns != 0) {
|
| - list.push({ type: 'empty' });
|
| - count++;
|
| - }
|
| - }
|
| -
|
| - return list;
|
| -};
|
| -
|
| -/**
|
| - * Decorates grid item.
|
| - * @param {HTMLLIElement} li The list item.
|
| - * @param {FileEntry} entry The file entry.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.decorateGridItem_ = function(li, entry) {
|
| - li.className = 'grid-item';
|
| - li.entry = entry;
|
| -
|
| - var frame = this.document_.createElement('div');
|
| - frame.className = 'grid-frame';
|
| - li.appendChild(frame);
|
| -
|
| - var box = this.document_.createElement('div');
|
| - box.className = 'img-container';
|
| - this.metadataCache_.get(entry, 'thumbnail|filesystem',
|
| - function(metadata) {
|
| - new ThumbnailLoader(entry.toURL(),
|
| - ThumbnailLoader.LoaderType.IMAGE,
|
| - metadata).
|
| - load(box, ThumbnailLoader.FillMode.FIT,
|
| - ThumbnailLoader.OptimizationMode.DISCARD_DETACHED);
|
| - });
|
| - frame.appendChild(box);
|
| -
|
| - var check = this.document_.createElement('div');
|
| - check.className = 'check';
|
| - li.appendChild(check);
|
| -};
|
| -
|
| -/**
|
| - * Handles the 'pick all/none' action.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onSelectAllNone_ = function() {
|
| - var sm = this.grid_.selectionModel;
|
| - if (sm.selectedIndexes.length == this.fileList_.length) {
|
| - sm.unselectAll();
|
| - } else {
|
| - sm.selectAll();
|
| - }
|
| -};
|
| -
|
| -/**
|
| - * Show error message.
|
| - * @param {string} message Error message.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onError_ = function(message) {
|
| - this.importingDialog_.hide(function() {
|
| - this.alert_.show(message,
|
| - function() {
|
| - window.close();
|
| - });
|
| - }.bind(this));
|
| -};
|
| -
|
| -/**
|
| - * Resize event handler.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onResize_ = function() {
|
| - var g = this.grid_;
|
| - g.startBatchUpdates();
|
| - setTimeout(function() {
|
| - g.columns = 0;
|
| - g.redraw();
|
| - g.endBatchUpdates();
|
| - }, 0);
|
| -};
|
| -
|
| -/**
|
| - * @return {Array.<Object>} The list of selected entries.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.getSelectedItems_ = function() {
|
| - var indexes = this.grid_.selectionModel.selectedIndexes;
|
| - var list = [];
|
| - for (var i = 0; i < indexes.length; i++) {
|
| - list.push(this.fileList_.item(indexes[i]));
|
| - }
|
| - return list;
|
| -};
|
| -
|
| -/**
|
| - * Event handler for picked items change.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onSelectionChanged_ = function() {
|
| - var count = this.grid_.selectionModel.selectedIndexes.length;
|
| - this.selectedCount_.textContent = count == 0 ? '' :
|
| - count == 1 ? loadTimeData.getString('PHOTO_IMPORT_ONE_SELECTED') :
|
| - loadTimeData.getStringF('PHOTO_IMPORT_MANY_SELECTED', count);
|
| - this.importButton_.disabled = count == 0 || this.myPhotosDirectory_ == null;
|
| - this.selectAllNone_.textContent = loadTimeData.getString(
|
| - count == this.fileList_.length && count > 0 ?
|
| - 'PHOTO_IMPORT_SELECT_NONE' : 'PHOTO_IMPORT_SELECT_ALL');
|
| -};
|
| -
|
| -/**
|
| - * Event handler for import button click.
|
| - * @param {Event} event The event.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onImportClick_ = function(event) {
|
| - var entries = this.getSelectedItems_();
|
| - var move = this.dom_.querySelector('#delete-after-checkbox').checked;
|
| - this.importingDialog_.show(entries, move);
|
| -
|
| - this.createDestination_(function() {
|
| - var percentage = Math.round(entries.length / this.fileList_.length * 100);
|
| - metrics.recordMediumCount('PhotoImport.ImportCount', entries.length);
|
| - metrics.recordSmallCount('PhotoImport.ImportPercentage', percentage);
|
| -
|
| - this.importingDialog_.start(this.destination_);
|
| - }.bind(this));
|
| -};
|
| -
|
| -/**
|
| - * Click event handler for the cancel button.
|
| - * @param {Event} event The event.
|
| - * @private
|
| - */
|
| -PhotoImport.prototype.onCancelClick_ = function(event) {
|
| - window.close();
|
| -};
|
| -
|
| -/**
|
| - * Item in the grid.
|
| - * @param {PhotoImport} app Application instance.
|
| - * @param {Entry} entry File entry.
|
| - * @constructor
|
| - */
|
| -function GridItem(app, entry) {
|
| - var li = app.document_.createElement('li');
|
| - li.__proto__ = GridItem.prototype;
|
| - app.decorateGridItem_(li, entry);
|
| - return li;
|
| -}
|
| -
|
| -GridItem.prototype = {
|
| - __proto__: cr.ui.ListItem.prototype,
|
| - get label() {},
|
| - set label(value) {}
|
| -};
|
| -
|
| -/**
|
| - * Creates a selection controller that is to be used with grid.
|
| - * @param {cr.ui.ListSelectionModel} selectionModel The selection model to
|
| - * interact with.
|
| - * @param {cr.ui.Grid} grid The grid to interact with.
|
| - * @constructor
|
| - * @extends {!cr.ui.ListSelectionController}
|
| - */
|
| -function GridSelectionController(selectionModel, grid) {
|
| - this.selectionModel_ = selectionModel;
|
| - this.grid_ = grid;
|
| -}
|
| -
|
| -/**
|
| - * Extends cr.ui.ListSelectionController.
|
| - */
|
| -GridSelectionController.prototype.__proto__ =
|
| - cr.ui.ListSelectionController.prototype;
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getIndexBelow = function(index) {
|
| - if (index == this.getLastIndex()) {
|
| - return -1;
|
| - }
|
| -
|
| - var dm = this.grid_.dataModel;
|
| - var columns = this.grid_.columns;
|
| - var min = (Math.floor(index / columns) + 1) * columns;
|
| -
|
| - for (var row = 1; true; row++) {
|
| - var end = index + columns * row;
|
| - var start = Math.max(min, index + columns * (row - 1));
|
| - if (start > dm.length) break;
|
| -
|
| - for (var i = end; i > start; i--) {
|
| - if (i < dm.length && dm.item(i).type == 'entry')
|
| - return i;
|
| - }
|
| - }
|
| -
|
| - return this.getLastIndex();
|
| -};
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getIndexAbove = function(index) {
|
| - if (index == this.getFirstIndex()) {
|
| - return -1;
|
| - }
|
| -
|
| - var dm = this.grid_.dataModel;
|
| - index -= this.grid_.columns;
|
| - while (index >= 0 && dm.item(index).type != 'entry') {
|
| - index--;
|
| - }
|
| -
|
| - return index < 0 ? this.getFirstIndex() : index;
|
| -};
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getIndexBefore = function(index) {
|
| - var dm = this.grid_.dataModel;
|
| - index--;
|
| - while (index >= 0 && dm.item(index).type != 'entry') {
|
| - index--;
|
| - }
|
| - return index;
|
| -};
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getIndexAfter = function(index) {
|
| - var dm = this.grid_.dataModel;
|
| - index++;
|
| - while (index < dm.length && dm.item(index).type != 'entry') {
|
| - index++;
|
| - }
|
| - return index == dm.length ? -1 : index;
|
| -};
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getFirstIndex = function() {
|
| - var dm = this.grid_.dataModel;
|
| - for (var index = 0; index < dm.length; index++) {
|
| - if (dm.item(index).type == 'entry')
|
| - return index;
|
| - }
|
| - return -1;
|
| -};
|
| -
|
| -/** @override */
|
| -GridSelectionController.prototype.getLastIndex = function() {
|
| - var dm = this.grid_.dataModel;
|
| - for (var index = dm.length - 1; index >= 0; index--) {
|
| - if (dm.item(index).type == 'entry')
|
| - return index;
|
| - }
|
| - return -1;
|
| -};
|
|
|