Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 document.addEventListener('DOMContentLoaded', function() { | 5 document.addEventListener('DOMContentLoaded', function() { |
| 6 PhotoImport.load(); | 6 PhotoImport.load(); |
| 7 }); | 7 }); |
| 8 | 8 |
| 9 /** | 9 /** |
| 10 * The main Photo App object. | 10 * The main Photo App object. |
| 11 * @param {HTMLElement} dom Container. | 11 * @param {HTMLElement} dom Container. |
| 12 * @param {FileSystem} filesystem Local file system. | 12 * @param {FileSystem} filesystem Local file system. |
| 13 * @param {Object} params Parameters. | 13 * @param {Object} params Parameters. |
| 14 * @constructor | 14 * @constructor |
| 15 */ | 15 */ |
| 16 function PhotoImport(dom, filesystem, params) { | 16 function PhotoImport(dom, filesystem, params) { |
| 17 this.filesystem_ = filesystem; | 17 this.filesystem_ = filesystem; |
| 18 this.dom_ = dom; | 18 this.dom_ = dom; |
| 19 this.document_ = this.dom_.ownerDocument; | 19 this.document_ = this.dom_.ownerDocument; |
| 20 this.metadataCache_ = params.metadataCache; | 20 this.metadataCache_ = params.metadataCache; |
| 21 this.volumeManager_ = new VolumeManager(); | 21 this.volumeManager_ = new VolumeManager(); |
| 22 this.copyManager_ = FileCopyManagerWrapper.getInstance(this.filesystem_.root); | 22 this.copyManager_ = FileCopyManagerWrapper.getInstance(this.filesystem_.root); |
| 23 this.mediaFilesList_ = null; | 23 this.mediaFilesList_ = null; |
| 24 this.albums_ = null; | 24 this.destination_ = null; |
| 25 this.albumsDir_ = null; | |
| 26 | 25 |
| 27 this.initDom_(); | 26 this.initDom_(); |
| 28 this.initAlbums_(); | 27 this.initDestination_(); |
| 29 this.loadSource_(params.source); | 28 this.loadSource_(params.source); |
| 30 } | 29 } |
| 31 | 30 |
| 32 PhotoImport.prototype = { __proto__: cr.EventTarget.prototype }; | 31 PhotoImport.prototype = { __proto__: cr.EventTarget.prototype }; |
| 33 | 32 |
| 34 /** | 33 /** |
| 35 * Single item width. | 34 * Single item width. |
| 36 * Keep in sync with .grid-item rule in photo_import.css. | 35 * Keep in sync with .grid-item rule in photo_import.css. |
| 37 */ | 36 */ |
| 38 PhotoImport.ITEM_WIDTH = 164 + 8; | 37 PhotoImport.ITEM_WIDTH = 164 + 8; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 103 loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER'); | 102 loadTimeData.getString('PHOTO_IMPORT_DELETE_AFTER'); |
| 104 this.pickedCount_ = this.dom_.querySelector('.picked-count'); | 103 this.pickedCount_ = this.dom_.querySelector('.picked-count'); |
| 105 | 104 |
| 106 this.importButton_ = this.dom_.querySelector('button.import'); | 105 this.importButton_ = this.dom_.querySelector('button.import'); |
| 107 this.importButton_.textContent = | 106 this.importButton_.textContent = |
| 108 loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON'); | 107 loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON'); |
| 109 this.importButton_.addEventListener('click', this.onImportClick_.bind(this)); | 108 this.importButton_.addEventListener('click', this.onImportClick_.bind(this)); |
| 110 | 109 |
| 111 this.grid_ = this.dom_.querySelector('grid'); | 110 this.grid_ = this.dom_.querySelector('grid'); |
| 112 cr.ui.Grid.decorate(this.grid_); | 111 cr.ui.Grid.decorate(this.grid_); |
| 113 this.onResize_(); // To set columns number. | |
| 114 this.grid_.itemConstructor = | 112 this.grid_.itemConstructor = |
| 115 GridItem.bind(null, this); | 113 GridItem.bind(null, this); |
| 116 this.fileList_ = new cr.ui.ArrayDataModel([]); | 114 this.fileList_ = new cr.ui.ArrayDataModel([]); |
| 117 this.grid_.selectionModel = new cr.ui.ListSelectionModel(); | 115 this.grid_.selectionModel = new cr.ui.ListSelectionModel(); |
| 118 this.grid_.dataModel = this.fileList_; | 116 this.grid_.dataModel = this.fileList_; |
| 119 this.grid_.activateItemAtIndex = this.onActivateItemAtIndex_.bind(this); | 117 this.grid_.activateItemAtIndex = this.onActivateItemAtIndex_.bind(this); |
| 120 this.grid_.addEventListener('keypress', this.onGridKeyPress_.bind(this)); | 118 this.grid_.addEventListener('keypress', this.onGridKeyPress_.bind(this)); |
| 121 this.onPickedItemsChanged_(); | 119 this.onPickedItemsChanged_(); |
| 122 | 120 |
| 123 this.selectAlbumDialog_ = new SelectAlbumDialog(this.dom_); | 121 this.importingDialog_ = new ImportingDialog(this.dom_, this.copyManager_, |
| 122 this.metadataCache_); | |
| 124 }; | 123 }; |
| 125 | 124 |
| 126 /** | 125 /** |
| 127 * One-time initialization of albums. | 126 * One-time initialization of destination directory. |
| 128 * @private | 127 * @private |
| 129 */ | 128 */ |
| 130 PhotoImport.prototype.initAlbums_ = function() { | 129 PhotoImport.prototype.initDestination_ = function() { |
| 131 var onError = this.onError_.bind( | 130 var onError = this.onError_.bind( |
| 132 this, loadTimeData.getString('PHOTO_IMPORT_GDATA_ERROR')); | 131 this, loadTimeData.getString('PHOTO_IMPORT_GDATA_ERROR')); |
| 133 | 132 |
| 134 var albums = []; | 133 var onDirectory = function(dir) { |
| 135 | 134 this.destination_ = dir; |
|
Vladislav Kaznacheev
2012/09/19 12:29:52
Not updating UI? Looks strange.
dgozman
2012/09/19 13:45:28
Nice catch. Fixed.
| |
| 136 var onEntry = function(entry) { | |
| 137 if (entry != null) { | |
| 138 albums.push(entry); | |
| 139 } else { | |
| 140 this.albums_ = albums; | |
| 141 } | |
| 142 }.bind(this); | |
| 143 | |
| 144 var onGData = function(gdata) { | |
| 145 this.albumsDir_ = gdata; | |
| 146 util.forEachDirEntry(gdata, onEntry); | |
| 147 }.bind(this); | 135 }.bind(this); |
| 148 | 136 |
| 149 var onMounted = function() { | 137 var onMounted = function() { |
| 150 var dir = PathUtil.join(RootDirectory.GDATA, PhotoImport.GDATA_PHOTOS_DIR); | 138 var dir = PathUtil.join(RootDirectory.GDATA, PhotoImport.GDATA_PHOTOS_DIR); |
| 151 util.getOrCreateDirectory(this.filesystem_.root, dir, onGData, onError); | 139 util.getOrCreateDirectory(this.filesystem_.root, dir, onDirectory, onError); |
| 152 }.bind(this); | 140 }.bind(this); |
| 153 | 141 |
| 154 if (this.volumeManager_.isMounted(RootDirectory.GDATA)) { | 142 if (this.volumeManager_.isMounted(RootDirectory.GDATA)) { |
| 155 onMounted(); | 143 onMounted(); |
| 156 } else { | 144 } else { |
| 157 this.volumeManager_.mountGData(onMounted, onError); | 145 this.volumeManager_.mountGData(onMounted, onError); |
| 158 } | 146 } |
| 159 }; | 147 }; |
| 160 | 148 |
| 161 /** | 149 /** |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 373 */ | 361 */ |
| 374 PhotoImport.prototype.onError_ = function(message) { | 362 PhotoImport.prototype.onError_ = function(message) { |
| 375 // TODO | 363 // TODO |
| 376 }; | 364 }; |
| 377 | 365 |
| 378 /** | 366 /** |
| 379 * Resize event handler. | 367 * Resize event handler. |
| 380 * @private | 368 * @private |
| 381 */ | 369 */ |
| 382 PhotoImport.prototype.onResize_ = function() { | 370 PhotoImport.prototype.onResize_ = function() { |
| 383 var columns = | 371 var g = this.grid_; |
| 384 Math.floor((this.dom_.clientWidth - 60) / PhotoImport.ITEM_WIDTH); | 372 g.startBatchUpdates(); |
| 385 if (columns != this.grid_.columns) { | 373 setTimeout(function() { |
| 386 this.grid_.columns = columns; | 374 g.columns = 0; |
| 387 this.fillGrid_(); | 375 g.redraw(); |
| 388 } | 376 g.endBatchUpdates(); |
| 377 }, 0); | |
| 389 }; | 378 }; |
| 390 | 379 |
| 391 /** | 380 /** |
| 392 * @return {Array.<Object>} The list of picked entries. | 381 * @return {Array.<Object>} The list of picked entries. |
| 393 * @private | 382 * @private |
| 394 */ | 383 */ |
| 395 PhotoImport.prototype.getPickedItems_ = function() { | 384 PhotoImport.prototype.getPickedItems_ = function() { |
| 396 var list = []; | 385 var list = []; |
| 397 for (var i = 0; i < this.fileList_.length; i++) { | 386 for (var i = 0; i < this.fileList_.length; i++) { |
| 398 var item = this.fileList_.item(i); | 387 var item = this.fileList_.item(i); |
| 399 if (item.picked) | 388 if (item.picked) |
| 400 list.push(item); | 389 list.push(item); |
| 401 } | 390 } |
| 402 return list; | 391 return list; |
| 403 }; | 392 }; |
| 404 | 393 |
| 405 /** | 394 /** |
| 406 * Event handler for selection change. | 395 * Event handler for selection change. |
| 407 * @param {Event} event The event. | 396 * @param {Event} event The event. |
| 408 * @private | 397 * @private |
| 409 */ | 398 */ |
| 410 PhotoImport.prototype.onPickedItemsChanged_ = function(event) { | 399 PhotoImport.prototype.onPickedItemsChanged_ = function(event) { |
| 411 var count = this.getPickedItems_().length; | 400 var count = this.getPickedItems_().length; |
| 412 this.pickedCount_.textContent = | 401 this.pickedCount_.textContent = |
| 413 count == 0 ? | 402 count == 0 ? |
| 414 loadTimeData.getString('PHOTO_IMPORT_NOTHING_PICKED') : | 403 loadTimeData.getString('PHOTO_IMPORT_NOTHING_PICKED') : |
| 415 count == 1 ? | 404 count == 1 ? |
| 416 loadTimeData.getString('PHOTO_IMPORT_ONE_PICKED') : | 405 loadTimeData.getString('PHOTO_IMPORT_ONE_PICKED') : |
| 417 loadTimeData.getStringF('PHOTO_IMPORT_MANY_PICKED', count); | 406 loadTimeData.getStringF('PHOTO_IMPORT_MANY_PICKED', count); |
| 418 this.importButton_.disabled = count == 0 || this.albums_ == null; | 407 this.importButton_.disabled = count == 0 || this.destination_ == null; |
| 419 }; | 408 }; |
| 420 | 409 |
| 421 /** | 410 /** |
| 422 * Event handler for import button click. | 411 * Event handler for import button click. |
| 423 * @param {Event} event The event. | 412 * @param {Event} event The event. |
| 424 * @private | 413 * @private |
| 425 */ | 414 */ |
| 426 PhotoImport.prototype.onImportClick_ = function(event) { | 415 PhotoImport.prototype.onImportClick_ = function(event) { |
| 427 var items = this.getPickedItems_(); | 416 var items = this.getPickedItems_(); |
| 428 | 417 var entries = items.map(function(item) { return item.entry; }); |
| 429 var defaultTitle = loadTimeData.getString('PHOTO_IMPORT_NEW_ALBUM_NAME'); | 418 var move = this.dom_.querySelector('#delete-after-checkbox').checked; |
| 430 var group = items[0].group; | 419 this.importingDialog_.show(entries, this.destination_, move); |
| 431 if (items.filter(function(i) { return i.group !== group }).length == 0) | |
| 432 defaultTitle = group.title; | |
| 433 | |
| 434 // TODO: use albums instead. | |
| 435 var dialogAlbums = []; | |
| 436 for (var index = 0; index < this.albums_.length; index++) { | |
| 437 dialogAlbums.push({ | |
| 438 name: this.albums_[index].name, | |
| 439 entry: this.albums_[index], | |
| 440 url: chrome.extension.getURL('../../images/filetype_large_audio.png') | |
| 441 }); | |
| 442 } | |
| 443 | |
| 444 this.selectAlbumDialog_.show( | |
| 445 items.length == 1 ? | |
| 446 loadTimeData.getString('PHOTO_IMPORT_SELECT_ALBUM_CAPTION') : | |
| 447 loadTimeData.getStringF('PHOTO_IMPORT_SELECT_ALBUM_CAPTION_PLURAL', | |
| 448 items.length), | |
| 449 dialogAlbums, | |
| 450 defaultTitle, | |
| 451 loadTimeData.getString('PHOTO_IMPORT_IMPORT_BUTTON'), | |
| 452 this.onAlbumSelected_.bind(this, items) | |
| 453 ); | |
| 454 }; | |
| 455 | |
| 456 /** | |
| 457 * Called when album is selected. | |
| 458 * @param {Array.<Object>} items List of items to import. | |
| 459 * @param {Object} album Album description. | |
| 460 * @private | |
| 461 */ | |
| 462 PhotoImport.prototype.onAlbumSelected_ = function(items, album) { | |
| 463 var entries = items.map(function(i) { return i.entry }); | |
| 464 | |
| 465 if (album.create) { | |
| 466 var onError = this.onError_.bind(this, | |
| 467 loadTimeData.getString('PHOTO_IMPORT_IMPORTING_ERROR')); | |
| 468 this.createAlbum_(album.name, | |
| 469 this.startImport_.bind(this, entries), | |
| 470 onError); | |
| 471 } else { | |
| 472 this.startImport_(entries, album.entry); | |
| 473 } | |
| 474 }; | |
| 475 | |
| 476 /** | |
| 477 * Starts importing process. | |
| 478 * @param {Array.<FileEntry>} entries List of entries to import. | |
| 479 * @param {DirectoryEntry} dir Where to import. | |
| 480 * @private | |
| 481 */ | |
| 482 PhotoImport.prototype.startImport_ = function(entries, dir) { | |
| 483 var files = entries.map(function(e) { return e.fullPath }).join('\n'); | |
| 484 var operationInfo = { | |
| 485 isCut: false, | |
| 486 isOnGData: PathUtil.getRootType(entries[0].fullPath) == RootType.GDATA, | |
| 487 sourceDir: null, | |
| 488 directories: '', | |
| 489 files: files | |
| 490 }; | |
| 491 this.copyManager_.paste(operationInfo, dir.fullPath, true); | |
| 492 }; | |
| 493 | |
| 494 /** | |
| 495 * Creates a directory for an album. | |
| 496 * @param {string} name Album name. | |
| 497 * @param {function(DirectoryEntry)} onSuccess Success callback. | |
| 498 * @param {function} onError Failure callback. | |
| 499 * @private | |
| 500 */ | |
| 501 PhotoImport.prototype.createAlbum_ = function(name, onSuccess, onError) { | |
| 502 var callback = function(entry) { | |
| 503 this.initAlbums_(); | |
| 504 onSuccess(entry); | |
| 505 }.bind(this); | |
| 506 | |
| 507 this.albumsDir_.getDirectory(name, { create: true, exclusive: true}, | |
| 508 callback, onError); | |
| 509 }; | 420 }; |
| 510 | 421 |
| 511 /** | 422 /** |
| 512 * Item in the grid. | 423 * Item in the grid. |
| 513 * @param {PhotoImport} app Application instance. | 424 * @param {PhotoImport} app Application instance. |
| 514 * @param {Entry} entry File entry. | 425 * @param {Entry} entry File entry. |
| 515 * @constructor | 426 * @constructor |
| 516 */ | 427 */ |
| 517 function GridItem(app, entry) { | 428 function GridItem(app, entry) { |
| 518 var li = app.document_.createElement('li'); | 429 var li = app.document_.createElement('li'); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 617 | 528 |
| 618 /** @inheritDoc */ | 529 /** @inheritDoc */ |
| 619 GridSelectionController.prototype.getLastIndex = function() { | 530 GridSelectionController.prototype.getLastIndex = function() { |
| 620 var dm = this.grid_.dataModel; | 531 var dm = this.grid_.dataModel; |
| 621 for (var index = dm.length - 1; index >= 0; index--) { | 532 for (var index = dm.length - 1; index >= 0; index--) { |
| 622 if (dm.item(index).type == 'entry') | 533 if (dm.item(index).type == 'entry') |
| 623 return index; | 534 return index; |
| 624 } | 535 } |
| 625 return -1; | 536 return -1; |
| 626 }; | 537 }; |
| OLD | NEW |