| 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 'use strict'; | 5 'use strict'; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * Slide mode displays a single image and has a set of controls to navigate | 8 * Slide mode displays a single image and has a set of controls to navigate |
| 9 * between the images and to edit an image. | 9 * between the images and to edit an image. |
| 10 * | 10 * |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 var overwriteOriginalBox = | 109 var overwriteOriginalBox = |
| 110 util.createChild(this.options_, 'overwrite-original'); | 110 util.createChild(this.options_, 'overwrite-original'); |
| 111 | 111 |
| 112 this.overwriteOriginal_ = util.createChild( | 112 this.overwriteOriginal_ = util.createChild( |
| 113 overwriteOriginalBox, 'common white', 'input'); | 113 overwriteOriginalBox, 'common white', 'input'); |
| 114 this.overwriteOriginal_.type = 'checkbox'; | 114 this.overwriteOriginal_.type = 'checkbox'; |
| 115 this.overwriteOriginal_.id = 'overwrite-checkbox'; | 115 this.overwriteOriginal_.id = 'overwrite-checkbox'; |
| 116 util.platform.getPreference(SlideMode.OVERWRITE_KEY, function(value) { | 116 util.platform.getPreference(SlideMode.OVERWRITE_KEY, function(value) { |
| 117 // Out-of-the box default is 'true' | 117 // Out-of-the box default is 'true' |
| 118 this.overwriteOriginal_.checked = | 118 this.overwriteOriginal_.checked = |
| 119 (typeof value != 'string' || value == 'true'); | 119 (typeof value !== 'string' || value === 'true'); |
| 120 }.bind(this)); | 120 }.bind(this)); |
| 121 this.overwriteOriginal_.addEventListener('click', | 121 this.overwriteOriginal_.addEventListener('click', |
| 122 this.onOverwriteOriginalClick_.bind(this)); | 122 this.onOverwriteOriginalClick_.bind(this)); |
| 123 | 123 |
| 124 var overwriteLabel = util.createChild(overwriteOriginalBox, '', 'label'); | 124 var overwriteLabel = util.createChild(overwriteOriginalBox, '', 'label'); |
| 125 overwriteLabel.textContent = | 125 overwriteLabel.textContent = |
| 126 this.displayStringFunction_('GALLERY_OVERWRITE_ORIGINAL'); | 126 this.displayStringFunction_('GALLERY_OVERWRITE_ORIGINAL'); |
| 127 overwriteLabel.setAttribute('for', 'overwrite-checkbox'); | 127 overwriteLabel.setAttribute('for', 'overwrite-checkbox'); |
| 128 | 128 |
| 129 this.bubble_ = util.createChild(this.toolbar_, 'bubble'); | 129 this.bubble_ = util.createChild(this.toolbar_, 'bubble'); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 | 261 |
| 262 // Wait 1000ms after the animation is done, then prefetch the next image. | 262 // Wait 1000ms after the animation is done, then prefetch the next image. |
| 263 this.requestPrefetch(1, delay + 1000); | 263 this.requestPrefetch(1, delay + 1000); |
| 264 | 264 |
| 265 if (loadCallback) loadCallback(); | 265 if (loadCallback) loadCallback(); |
| 266 }.bind(this); | 266 }.bind(this); |
| 267 | 267 |
| 268 // The latest |leave| call might have left the image animating. Remove it. | 268 // The latest |leave| call might have left the image animating. Remove it. |
| 269 this.unloadImage_(); | 269 this.unloadImage_(); |
| 270 | 270 |
| 271 if (this.getItemCount_() == 0) { | 271 if (this.getItemCount_() === 0) { |
| 272 this.displayedIndex_ = -1; | 272 this.displayedIndex_ = -1; |
| 273 //TODO(kaznacheev) Show this message in the grid mode too. | 273 //TODO(kaznacheev) Show this message in the grid mode too. |
| 274 this.showErrorBanner_('GALLERY_NO_IMAGES'); | 274 this.showErrorBanner_('GALLERY_NO_IMAGES'); |
| 275 loadDone(); | 275 loadDone(); |
| 276 } else { | 276 } else { |
| 277 // Remember the selection if it is empty or multiple. It will be restored | 277 // Remember the selection if it is empty or multiple. It will be restored |
| 278 // in |leave| if the user did not changing the selection manually. | 278 // in |leave| if the user did not changing the selection manually. |
| 279 var currentSelection = this.selectionModel_.selectedIndexes; | 279 var currentSelection = this.selectionModel_.selectedIndexes; |
| 280 if (currentSelection.length == 1) | 280 if (currentSelection.length === 1) |
| 281 this.savedSelection_ = null; | 281 this.savedSelection_ = null; |
| 282 else | 282 else |
| 283 this.savedSelection_ = currentSelection; | 283 this.savedSelection_ = currentSelection; |
| 284 | 284 |
| 285 // Ensure valid single selection. | 285 // Ensure valid single selection. |
| 286 // Note that the SlideMode object is not listening to selection change yet. | 286 // Note that the SlideMode object is not listening to selection change yet. |
| 287 this.select(Math.max(0, this.getSelectedIndex())); | 287 this.select(Math.max(0, this.getSelectedIndex())); |
| 288 this.displayedIndex_ = this.getSelectedIndex(); | 288 this.displayedIndex_ = this.getSelectedIndex(); |
| 289 | 289 |
| 290 var selectedItem = this.getSelectedItem(); | 290 var selectedItem = this.getSelectedItem(); |
| 291 var selectedUrl = selectedItem.getUrl(); | |
| 292 // Show the selected item ASAP, then complete the initialization | 291 // Show the selected item ASAP, then complete the initialization |
| 293 // (loading the ribbon thumbnails can take some time). | 292 // (loading the ribbon thumbnails can take some time). |
| 294 this.metadataCache_.get(selectedUrl, Gallery.METADATA_TYPE, | 293 this.metadataCache_.get(selectedItem.getEntry(), Gallery.METADATA_TYPE, |
| 295 function(metadata) { | 294 function(metadata) { |
| 296 this.loadItem_(selectedUrl, metadata, | 295 this.loadItem_(selectedItem.getEntry(), metadata, |
| 297 zoomFromRect && this.imageView_.createZoomEffect(zoomFromRect), | 296 zoomFromRect && this.imageView_.createZoomEffect(zoomFromRect), |
| 298 displayCallback, loadDone); | 297 displayCallback, loadDone); |
| 299 }.bind(this)); | 298 }.bind(this)); |
| 300 | 299 |
| 301 } | 300 } |
| 302 }; | 301 }; |
| 303 | 302 |
| 304 /** | 303 /** |
| 305 * Leave the mode. | 304 * Leave the mode. |
| 306 * @param {Rect} zoomToRect Rectangle for zoom effect. | 305 * @param {Rect} zoomToRect Rectangle for zoom effect. |
| (...skipping 10 matching lines...) Expand all Loading... |
| 317 this.dataModel_.removeEventListener('splice', this.onSpliceBound_); | 316 this.dataModel_.removeEventListener('splice', this.onSpliceBound_); |
| 318 this.dataModel_.removeEventListener('content', this.onContentBound_); | 317 this.dataModel_.removeEventListener('content', this.onContentBound_); |
| 319 this.ribbon_.disable(); | 318 this.ribbon_.disable(); |
| 320 this.active_ = false; | 319 this.active_ = false; |
| 321 if (this.savedSelection_) | 320 if (this.savedSelection_) |
| 322 this.selectionModel_.selectedIndexes = this.savedSelection_; | 321 this.selectionModel_.selectedIndexes = this.savedSelection_; |
| 323 this.unloadImage_(zoomToRect); | 322 this.unloadImage_(zoomToRect); |
| 324 callback(); | 323 callback(); |
| 325 }.bind(this); | 324 }.bind(this); |
| 326 | 325 |
| 327 if (this.getItemCount_() == 0) { | 326 if (this.getItemCount_() === 0) { |
| 328 this.showErrorBanner_(false); | 327 this.showErrorBanner_(false); |
| 329 commitDone(); | 328 commitDone(); |
| 330 } else { | 329 } else { |
| 331 this.commitItem_(commitDone); | 330 this.commitItem_(commitDone); |
| 332 } | 331 } |
| 333 | 332 |
| 334 // Disable the slide-mode only buttons when leaving. | 333 // Disable the slide-mode only buttons when leaving. |
| 335 this.editButton_.setAttribute('disabled', ''); | 334 this.editButton_.setAttribute('disabled', ''); |
| 336 this.printButton_.setAttribute('disabled', ''); | 335 this.printButton_.setAttribute('disabled', ''); |
| 337 }; | 336 }; |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 !util.isFullScreen(this.context_.appWindow)); | 401 !util.isFullScreen(this.context_.appWindow)); |
| 403 }; | 402 }; |
| 404 | 403 |
| 405 /** | 404 /** |
| 406 * Selection change handler. | 405 * Selection change handler. |
| 407 * | 406 * |
| 408 * Commits the current image and displays the newly selected image. | 407 * Commits the current image and displays the newly selected image. |
| 409 * @private | 408 * @private |
| 410 */ | 409 */ |
| 411 SlideMode.prototype.onSelection_ = function() { | 410 SlideMode.prototype.onSelection_ = function() { |
| 412 if (this.selectionModel_.selectedIndexes.length == 0) | 411 if (this.selectionModel_.selectedIndexes.length === 0) |
| 413 return; // Temporary empty selection. | 412 return; // Temporary empty selection. |
| 414 | 413 |
| 415 // Forget the saved selection if the user changed the selection manually. | 414 // Forget the saved selection if the user changed the selection manually. |
| 416 if (!this.isSlideshowOn_()) | 415 if (!this.isSlideshowOn_()) |
| 417 this.savedSelection_ = null; | 416 this.savedSelection_ = null; |
| 418 | 417 |
| 419 if (this.getSelectedIndex() == this.displayedIndex_) | 418 if (this.getSelectedIndex() === this.displayedIndex_) |
| 420 return; // Do not reselect. | 419 return; // Do not reselect. |
| 421 | 420 |
| 422 this.commitItem_(this.loadSelectedItem_.bind(this)); | 421 this.commitItem_(this.loadSelectedItem_.bind(this)); |
| 423 }; | 422 }; |
| 424 | 423 |
| 425 /** | 424 /** |
| 426 * Handles changes in tools visibility, and if the header is dimmed, then | 425 * Handles changes in tools visibility, and if the header is dimmed, then |
| 427 * requests disabling the draggable app region. | 426 * requests disabling the draggable app region. |
| 428 * | 427 * |
| 429 * @private | 428 * @private |
| (...skipping 19 matching lines...) Expand all Loading... |
| 449 /** | 448 /** |
| 450 * Load the selected item. | 449 * Load the selected item. |
| 451 * | 450 * |
| 452 * @private | 451 * @private |
| 453 */ | 452 */ |
| 454 SlideMode.prototype.loadSelectedItem_ = function() { | 453 SlideMode.prototype.loadSelectedItem_ = function() { |
| 455 var slideHint = this.slideHint_; | 454 var slideHint = this.slideHint_; |
| 456 this.slideHint_ = undefined; | 455 this.slideHint_ = undefined; |
| 457 | 456 |
| 458 var index = this.getSelectedIndex(); | 457 var index = this.getSelectedIndex(); |
| 459 if (index == this.displayedIndex_) | 458 if (index === this.displayedIndex_) |
| 460 return; // Do not reselect. | 459 return; // Do not reselect. |
| 461 | 460 |
| 462 var step = slideHint || (index - this.displayedIndex_); | 461 var step = slideHint || (index - this.displayedIndex_); |
| 463 | 462 |
| 464 if (Math.abs(step) != 1) { | 463 if (Math.abs(step) != 1) { |
| 465 // Long leap, the sequence is broken, we have no good prefetch candidate. | 464 // Long leap, the sequence is broken, we have no good prefetch candidate. |
| 466 this.sequenceDirection_ = 0; | 465 this.sequenceDirection_ = 0; |
| 467 this.sequenceLength_ = 0; | 466 this.sequenceLength_ = 0; |
| 468 } else if (this.sequenceDirection_ == step) { | 467 } else if (this.sequenceDirection_ === step) { |
| 469 // Keeping going in sequence. | 468 // Keeping going in sequence. |
| 470 this.sequenceLength_++; | 469 this.sequenceLength_++; |
| 471 } else { | 470 } else { |
| 472 // Reversed the direction. Reset the counter. | 471 // Reversed the direction. Reset the counter. |
| 473 this.sequenceDirection_ = step; | 472 this.sequenceDirection_ = step; |
| 474 this.sequenceLength_ = 1; | 473 this.sequenceLength_ = 1; |
| 475 } | 474 } |
| 476 | 475 |
| 477 if (this.sequenceLength_ <= 1) { | 476 if (this.sequenceLength_ <= 1) { |
| 478 // We have just broke the sequence. Touch the current image so that it stays | 477 // We have just broke the sequence. Touch the current image so that it stays |
| 479 // in the cache longer. | 478 // in the cache longer. |
| 480 this.imageView_.prefetch(this.imageView_.contentID_); | 479 this.imageView_.prefetch(this.imageView_.contentEntry_); |
| 481 } | 480 } |
| 482 | 481 |
| 483 this.displayedIndex_ = index; | 482 this.displayedIndex_ = index; |
| 484 | 483 |
| 485 function shouldPrefetch(loadType, step, sequenceLength) { | 484 function shouldPrefetch(loadType, step, sequenceLength) { |
| 486 // Never prefetch when selecting out of sequence. | 485 // Never prefetch when selecting out of sequence. |
| 487 if (Math.abs(step) != 1) | 486 if (Math.abs(step) != 1) |
| 488 return false; | 487 return false; |
| 489 | 488 |
| 490 // Never prefetch after a video load (decoding the next image can freeze | 489 // Never prefetch after a video load (decoding the next image can freeze |
| 491 // the UI for a second or two). | 490 // the UI for a second or two). |
| 492 if (loadType == ImageView.LOAD_TYPE_VIDEO_FILE) | 491 if (loadType === ImageView.LOAD_TYPE_VIDEO_FILE) |
| 493 return false; | 492 return false; |
| 494 | 493 |
| 495 // Always prefetch if the previous load was from cache. | 494 // Always prefetch if the previous load was from cache. |
| 496 if (loadType == ImageView.LOAD_TYPE_CACHED_FULL) | 495 if (loadType === ImageView.LOAD_TYPE_CACHED_FULL) |
| 497 return true; | 496 return true; |
| 498 | 497 |
| 499 // Prefetch if we have been going in the same direction for long enough. | 498 // Prefetch if we have been going in the same direction for long enough. |
| 500 return sequenceLength >= 3; | 499 return sequenceLength >= 3; |
| 501 } | 500 } |
| 502 | 501 |
| 503 var selectedItem = this.getSelectedItem(); | 502 var selectedItem = this.getSelectedItem(); |
| 504 this.currentUniqueKey_++; | 503 this.currentUniqueKey_++; |
| 505 var selectedUniqueKey = this.currentUniqueKey_; | 504 var selectedUniqueKey = this.currentUniqueKey_; |
| 506 var onMetadata = function(metadata) { | 505 var onMetadata = function(metadata) { |
| 507 // Discard, since another load has been invoked after this one. | 506 // Discard, since another load has been invoked after this one. |
| 508 if (selectedUniqueKey != this.currentUniqueKey_) return; | 507 if (selectedUniqueKey != this.currentUniqueKey_) return; |
| 509 this.loadItem_(selectedItem.getUrl(), metadata, | 508 this.loadItem_(selectedItem.getEntry(), metadata, |
| 510 new ImageView.Effect.Slide(step, this.isSlideshowPlaying_()), | 509 new ImageView.Effect.Slide(step, this.isSlideshowPlaying_()), |
| 511 function() {} /* no displayCallback */, | 510 function() {} /* no displayCallback */, |
| 512 function(loadType, delay) { | 511 function(loadType, delay) { |
| 513 // Discard, since another load has been invoked after this one. | 512 // Discard, since another load has been invoked after this one. |
| 514 if (selectedUniqueKey != this.currentUniqueKey_) return; | 513 if (selectedUniqueKey != this.currentUniqueKey_) return; |
| 515 if (shouldPrefetch(loadType, step, this.sequenceLength_)) { | 514 if (shouldPrefetch(loadType, step, this.sequenceLength_)) { |
| 516 this.requestPrefetch(step, delay); | 515 this.requestPrefetch(step, delay); |
| 517 } | 516 } |
| 518 if (this.isSlideshowPlaying_()) | 517 if (this.isSlideshowPlaying_()) |
| 519 this.scheduleNextSlide_(); | 518 this.scheduleNextSlide_(); |
| 520 }.bind(this)); | 519 }.bind(this)); |
| 521 }.bind(this); | 520 }.bind(this); |
| 522 this.metadataCache_.get( | 521 this.metadataCache_.get( |
| 523 selectedItem.getUrl(), Gallery.METADATA_TYPE, onMetadata); | 522 selectedItem.getEntry(), Gallery.METADATA_TYPE, onMetadata); |
| 524 }; | 523 }; |
| 525 | 524 |
| 526 /** | 525 /** |
| 527 * Unload the current image. | 526 * Unload the current image. |
| 528 * | 527 * |
| 529 * @param {Rect} zoomToRect Rectangle for zoom effect. | 528 * @param {Rect} zoomToRect Rectangle for zoom effect. |
| 530 * @private | 529 * @private |
| 531 */ | 530 */ |
| 532 SlideMode.prototype.unloadImage_ = function(zoomToRect) { | 531 SlideMode.prototype.unloadImage_ = function(zoomToRect) { |
| 533 this.imageView_.unload(zoomToRect); | 532 this.imageView_.unload(zoomToRect); |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 /** | 573 /** |
| 575 * @param {number} direction -1 for left, 1 for right. | 574 * @param {number} direction -1 for left, 1 for right. |
| 576 * @return {number} Next index in the given direction, with wrapping. | 575 * @return {number} Next index in the given direction, with wrapping. |
| 577 * @private | 576 * @private |
| 578 */ | 577 */ |
| 579 SlideMode.prototype.getNextSelectedIndex_ = function(direction) { | 578 SlideMode.prototype.getNextSelectedIndex_ = function(direction) { |
| 580 function advance(index, limit) { | 579 function advance(index, limit) { |
| 581 index += (direction > 0 ? 1 : -1); | 580 index += (direction > 0 ? 1 : -1); |
| 582 if (index < 0) | 581 if (index < 0) |
| 583 return limit - 1; | 582 return limit - 1; |
| 584 if (index == limit) | 583 if (index === limit) |
| 585 return 0; | 584 return 0; |
| 586 return index; | 585 return index; |
| 587 } | 586 } |
| 588 | 587 |
| 589 // If the saved selection is multiple the Slideshow should cycle through | 588 // If the saved selection is multiple the Slideshow should cycle through |
| 590 // the saved selection. | 589 // the saved selection. |
| 591 if (this.isSlideshowOn_() && | 590 if (this.isSlideshowOn_() && |
| 592 this.savedSelection_ && this.savedSelection_.length > 1) { | 591 this.savedSelection_ && this.savedSelection_.length > 1) { |
| 593 var pos = advance(this.savedSelection_.indexOf(this.getSelectedIndex()), | 592 var pos = advance(this.savedSelection_.indexOf(this.getSelectedIndex()), |
| 594 this.savedSelection_.length); | 593 this.savedSelection_.length); |
| 595 return this.savedSelection_[pos]; | 594 return this.savedSelection_[pos]; |
| 596 } else { | 595 } else { |
| 597 return advance(this.getSelectedIndex(), this.getItemCount_()); | 596 return advance(this.getSelectedIndex(), this.getItemCount_()); |
| 598 } | 597 } |
| 599 }; | 598 }; |
| 600 | 599 |
| 601 /** | 600 /** |
| 602 * Advance the selection based on the pressed key ID. | 601 * Advance the selection based on the pressed key ID. |
| 603 * @param {string} keyID Key identifier. | 602 * @param {string} keyID Key identifier. |
| 604 */ | 603 */ |
| 605 SlideMode.prototype.advanceWithKeyboard = function(keyID) { | 604 SlideMode.prototype.advanceWithKeyboard = function(keyID) { |
| 606 this.advanceManually(keyID == 'Up' || keyID == 'Left' ? -1 : 1); | 605 this.advanceManually(keyID === 'Up' || keyID === 'Left' ? -1 : 1); |
| 607 }; | 606 }; |
| 608 | 607 |
| 609 /** | 608 /** |
| 610 * Advance the selection as a result of a user action (as opposed to an | 609 * Advance the selection as a result of a user action (as opposed to an |
| 611 * automatic change in the slideshow mode). | 610 * automatic change in the slideshow mode). |
| 612 * @param {number} direction -1 for left, 1 for right. | 611 * @param {number} direction -1 for left, 1 for right. |
| 613 */ | 612 */ |
| 614 SlideMode.prototype.advanceManually = function(direction) { | 613 SlideMode.prototype.advanceManually = function(direction) { |
| 615 if (this.isSlideshowPlaying_()) { | 614 if (this.isSlideshowPlaying_()) { |
| 616 this.pauseSlideshow_(); | 615 this.pauseSlideshow_(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 639 */ | 638 */ |
| 640 SlideMode.prototype.selectLast = function() { | 639 SlideMode.prototype.selectLast = function() { |
| 641 this.select(this.getItemCount_() - 1); | 640 this.select(this.getItemCount_() - 1); |
| 642 }; | 641 }; |
| 643 | 642 |
| 644 // Loading/unloading | 643 // Loading/unloading |
| 645 | 644 |
| 646 /** | 645 /** |
| 647 * Load and display an item. | 646 * Load and display an item. |
| 648 * | 647 * |
| 649 * @param {string} url Item url. | 648 * @param {FileEntry} entry Item entry to be loaded. |
| 650 * @param {Object} metadata Item metadata. | 649 * @param {Object} metadata Item metadata. |
| 651 * @param {Object} effect Transition effect object. | 650 * @param {Object} effect Transition effect object. |
| 652 * @param {function} displayCallback Called when the image is displayed | 651 * @param {function} displayCallback Called when the image is displayed |
| 653 * (which can happen before the image load due to caching). | 652 * (which can happen before the image load due to caching). |
| 654 * @param {function} loadCallback Called when the image is fully loaded. | 653 * @param {function} loadCallback Called when the image is fully loaded. |
| 655 * @private | 654 * @private |
| 656 */ | 655 */ |
| 657 SlideMode.prototype.loadItem_ = function( | 656 SlideMode.prototype.loadItem_ = function( |
| 658 url, metadata, effect, displayCallback, loadCallback) { | 657 entry, metadata, effect, displayCallback, loadCallback) { |
| 659 this.selectedImageMetadata_ = MetadataCache.cloneMetadata(metadata); | 658 this.selectedImageMetadata_ = MetadataCache.cloneMetadata(metadata); |
| 660 | 659 |
| 661 this.showSpinner_(true); | 660 this.showSpinner_(true); |
| 662 | 661 |
| 663 var loadDone = function(loadType, delay, error) { | 662 var loadDone = function(loadType, delay, error) { |
| 664 var video = this.isShowingVideo_(); | 663 var video = this.isShowingVideo_(); |
| 665 ImageUtil.setAttribute(this.container_, 'video', video); | 664 ImageUtil.setAttribute(this.container_, 'video', video); |
| 666 | 665 |
| 667 this.showSpinner_(false); | 666 this.showSpinner_(false); |
| 668 if (loadType == ImageView.LOAD_TYPE_ERROR) { | 667 if (loadType === ImageView.LOAD_TYPE_ERROR) { |
| 669 // if we have a specific error, then display it | 668 // if we have a specific error, then display it |
| 670 if (error) { | 669 if (error) { |
| 671 this.showErrorBanner_(error); | 670 this.showErrorBanner_(error); |
| 672 } else { | 671 } else { |
| 673 // otherwise try to infer general error | 672 // otherwise try to infer general error |
| 674 this.showErrorBanner_( | 673 this.showErrorBanner_( |
| 675 video ? 'GALLERY_VIDEO_ERROR' : 'GALLERY_IMAGE_ERROR'); | 674 video ? 'GALLERY_VIDEO_ERROR' : 'GALLERY_IMAGE_ERROR'); |
| 676 } | 675 } |
| 677 } else if (loadType == ImageView.LOAD_TYPE_OFFLINE) { | 676 } else if (loadType === ImageView.LOAD_TYPE_OFFLINE) { |
| 678 this.showErrorBanner_( | 677 this.showErrorBanner_( |
| 679 video ? 'GALLERY_VIDEO_OFFLINE' : 'GALLERY_IMAGE_OFFLINE'); | 678 video ? 'GALLERY_VIDEO_OFFLINE' : 'GALLERY_IMAGE_OFFLINE'); |
| 680 } | 679 } |
| 681 | 680 |
| 682 if (video) { | 681 if (video) { |
| 683 // The editor toolbar does not make sense for video, hide it. | 682 // The editor toolbar does not make sense for video, hide it. |
| 684 this.stopEditing_(); | 683 this.stopEditing_(); |
| 685 this.mediaControls_.attachMedia(this.imageView_.getVideo()); | 684 this.mediaControls_.attachMedia(this.imageView_.getVideo()); |
| 686 | 685 |
| 687 // TODO(kaznacheev): Add metrics for video playback. | 686 // TODO(kaznacheev): Add metrics for video playback. |
| 688 } else { | 687 } else { |
| 689 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('View')); | 688 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('View')); |
| 690 | 689 |
| 691 var toMillions = function(number) { | 690 var toMillions = function(number) { |
| 692 return Math.round(number / (1000 * 1000)); | 691 return Math.round(number / (1000 * 1000)); |
| 693 }; | 692 }; |
| 694 | 693 |
| 695 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MB'), | 694 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MB'), |
| 696 toMillions(metadata.filesystem.size)); | 695 toMillions(metadata.filesystem.size)); |
| 697 | 696 |
| 698 var canvas = this.imageView_.getCanvas(); | 697 var canvas = this.imageView_.getCanvas(); |
| 699 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MPix'), | 698 ImageUtil.metrics.recordSmallCount(ImageUtil.getMetricName('Size.MPix'), |
| 700 toMillions(canvas.width * canvas.height)); | 699 toMillions(canvas.width * canvas.height)); |
| 701 | 700 |
| 702 var extIndex = url.lastIndexOf('.'); | 701 var extIndex = entry.name.lastIndexOf('.'); |
| 703 var ext = extIndex < 0 ? '' : url.substr(extIndex + 1).toLowerCase(); | 702 var ext = extIndex < 0 ? '' : |
| 704 if (ext == 'jpeg') ext = 'jpg'; | 703 entry.name.substr(extIndex + 1).toLowerCase(); |
| 704 if (ext === 'jpeg') ext = 'jpg'; |
| 705 ImageUtil.metrics.recordEnum( | 705 ImageUtil.metrics.recordEnum( |
| 706 ImageUtil.getMetricName('FileType'), ext, ImageUtil.FILE_TYPES); | 706 ImageUtil.getMetricName('FileType'), ext, ImageUtil.FILE_TYPES); |
| 707 } | 707 } |
| 708 | 708 |
| 709 // Enable or disable buttons for editing and printing. | 709 // Enable or disable buttons for editing and printing. |
| 710 if (video || error) { | 710 if (video || error) { |
| 711 this.editButton_.setAttribute('disabled', ''); | 711 this.editButton_.setAttribute('disabled', ''); |
| 712 this.printButton_.setAttribute('disabled', ''); | 712 this.printButton_.setAttribute('disabled', ''); |
| 713 } else { | 713 } else { |
| 714 this.editButton_.removeAttribute('disabled'); | 714 this.editButton_.removeAttribute('disabled'); |
| 715 this.printButton_.removeAttribute('disabled'); | 715 this.printButton_.removeAttribute('disabled'); |
| 716 } | 716 } |
| 717 | 717 |
| 718 // For once edited image, disallow the 'overwrite' setting change. | 718 // For once edited image, disallow the 'overwrite' setting change. |
| 719 ImageUtil.setAttribute(this.options_, 'saved', | 719 ImageUtil.setAttribute(this.options_, 'saved', |
| 720 !this.getSelectedItem().isOriginal()); | 720 !this.getSelectedItem().isOriginal()); |
| 721 | 721 |
| 722 util.platform.getPreference(SlideMode.OVERWRITE_BUBBLE_KEY, | 722 util.platform.getPreference(SlideMode.OVERWRITE_BUBBLE_KEY, |
| 723 function(value) { | 723 function(value) { |
| 724 var times = typeof value == 'string' ? parseInt(value, 10) : 0; | 724 var times = typeof value === 'string' ? parseInt(value, 10) : 0; |
| 725 if (times < SlideMode.OVERWRITE_BUBBLE_MAX_TIMES) { | 725 if (times < SlideMode.OVERWRITE_BUBBLE_MAX_TIMES) { |
| 726 this.bubble_.hidden = false; | 726 this.bubble_.hidden = false; |
| 727 if (this.isEditing()) { | 727 if (this.isEditing()) { |
| 728 util.platform.setPreference( | 728 util.platform.setPreference( |
| 729 SlideMode.OVERWRITE_BUBBLE_KEY, times + 1); | 729 SlideMode.OVERWRITE_BUBBLE_KEY, times + 1); |
| 730 } | 730 } |
| 731 } | 731 } |
| 732 }.bind(this)); | 732 }.bind(this)); |
| 733 | 733 |
| 734 loadCallback(loadType, delay); | 734 loadCallback(loadType, delay); |
| 735 }.bind(this); | 735 }.bind(this); |
| 736 | 736 |
| 737 var displayDone = function() { | 737 var displayDone = function() { |
| 738 cr.dispatchSimpleEvent(this, 'image-displayed'); | 738 cr.dispatchSimpleEvent(this, 'image-displayed'); |
| 739 displayCallback(); | 739 displayCallback(); |
| 740 }.bind(this); | 740 }.bind(this); |
| 741 | 741 |
| 742 this.editor_.openSession(url, metadata, effect, | 742 this.editor_.openSession(entry, metadata, effect, |
| 743 this.saveCurrentImage_.bind(this), displayDone, loadDone); | 743 this.saveCurrentImage_.bind(this), displayDone, loadDone); |
| 744 }; | 744 }; |
| 745 | 745 |
| 746 /** | 746 /** |
| 747 * Commit changes to the current item and reset all messages/indicators. | 747 * Commit changes to the current item and reset all messages/indicators. |
| 748 * | 748 * |
| 749 * @param {function} callback Callback. | 749 * @param {function} callback Callback. |
| 750 * @private | 750 * @private |
| 751 */ | 751 */ |
| 752 SlideMode.prototype.commitItem_ = function(callback) { | 752 SlideMode.prototype.commitItem_ = function(callback) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 774 * Request a prefetch for the next image. | 774 * Request a prefetch for the next image. |
| 775 * | 775 * |
| 776 * @param {number} direction -1 or 1. | 776 * @param {number} direction -1 or 1. |
| 777 * @param {number} delay Delay in ms. Used to prevent the CPU-heavy image | 777 * @param {number} delay Delay in ms. Used to prevent the CPU-heavy image |
| 778 * loading from disrupting the animation that might be still in progress. | 778 * loading from disrupting the animation that might be still in progress. |
| 779 */ | 779 */ |
| 780 SlideMode.prototype.requestPrefetch = function(direction, delay) { | 780 SlideMode.prototype.requestPrefetch = function(direction, delay) { |
| 781 if (this.getItemCount_() <= 1) return; | 781 if (this.getItemCount_() <= 1) return; |
| 782 | 782 |
| 783 var index = this.getNextSelectedIndex_(direction); | 783 var index = this.getNextSelectedIndex_(direction); |
| 784 var nextItemUrl = this.getItem(index).getUrl(); | 784 var nextItemEntry = this.getItem(index).getEntry(); |
| 785 this.imageView_.prefetch(nextItemUrl, delay); | 785 this.imageView_.prefetch(nextItemEntry, delay); |
| 786 }; | 786 }; |
| 787 | 787 |
| 788 // Event handlers. | 788 // Event handlers. |
| 789 | 789 |
| 790 /** | 790 /** |
| 791 * Unload handler, to be called from the top frame. | 791 * Unload handler, to be called from the top frame. |
| 792 * @param {boolean} exiting True if the app is exiting. | 792 * @param {boolean} exiting True if the app is exiting. |
| 793 */ | 793 */ |
| 794 SlideMode.prototype.onUnload = function(exiting) { | 794 SlideMode.prototype.onUnload = function(exiting) { |
| 795 if (this.isShowingVideo_() && this.mediaControls_.isPlaying()) { | 795 if (this.isShowingVideo_() && this.mediaControls_.isPlaying()) { |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 935 // Saving | 935 // Saving |
| 936 | 936 |
| 937 /** | 937 /** |
| 938 * Save the current image to a file. | 938 * Save the current image to a file. |
| 939 * | 939 * |
| 940 * @param {function} callback Callback. | 940 * @param {function} callback Callback. |
| 941 * @private | 941 * @private |
| 942 */ | 942 */ |
| 943 SlideMode.prototype.saveCurrentImage_ = function(callback) { | 943 SlideMode.prototype.saveCurrentImage_ = function(callback) { |
| 944 var item = this.getSelectedItem(); | 944 var item = this.getSelectedItem(); |
| 945 var oldUrl = item.getUrl(); | 945 var oldEntry = item.getEntry(); |
| 946 var canvas = this.imageView_.getCanvas(); | 946 var canvas = this.imageView_.getCanvas(); |
| 947 | 947 |
| 948 this.showSpinner_(true); | 948 this.showSpinner_(true); |
| 949 var metadataEncoder = ImageEncoder.encodeMetadata( | 949 var metadataEncoder = ImageEncoder.encodeMetadata( |
| 950 this.selectedImageMetadata_.media, canvas, 1 /* quality */); | 950 this.selectedImageMetadata_.media, canvas, 1 /* quality */); |
| 951 | 951 |
| 952 this.selectedImageMetadata_ = ContentProvider.ConvertContentMetadata( | 952 this.selectedImageMetadata_ = ContentProvider.ConvertContentMetadata( |
| 953 metadataEncoder.getMetadata(), this.selectedImageMetadata_); | 953 metadataEncoder.getMetadata(), this.selectedImageMetadata_); |
| 954 | 954 |
| 955 item.saveToFile( | 955 item.saveToFile( |
| 956 this.context_.saveDirEntry, | 956 this.context_.saveDirEntry, |
| 957 this.shouldOverwriteOriginal_(), | 957 this.shouldOverwriteOriginal_(), |
| 958 canvas, | 958 canvas, |
| 959 metadataEncoder, | 959 metadataEncoder, |
| 960 function(success) { | 960 function(success) { |
| 961 // TODO(kaznacheev): Implement write error handling. | 961 // TODO(kaznacheev): Implement write error handling. |
| 962 // Until then pretend that the save succeeded. | 962 // Until then pretend that the save succeeded. |
| 963 this.showSpinner_(false); | 963 this.showSpinner_(false); |
| 964 this.flashSavedLabel_(); | 964 this.flashSavedLabel_(); |
| 965 | 965 |
| 966 var e = new Event('content'); | 966 var event = new Event('content'); |
| 967 e.item = item; | 967 event.item = item; |
| 968 e.oldUrl = oldUrl; | 968 event.oldEntry = oldEntry; |
| 969 e.metadata = this.selectedImageMetadata_; | 969 event.metadata = this.selectedImageMetadata_; |
| 970 this.dataModel_.dispatchEvent(e); | 970 this.dataModel_.dispatchEvent(event); |
| 971 | 971 |
| 972 // Allow changing the 'Overwrite original' setting only if the user | 972 // Allow changing the 'Overwrite original' setting only if the user |
| 973 // used Undo to restore the original image AND it is not a copy. | 973 // used Undo to restore the original image AND it is not a copy. |
| 974 // Otherwise lock the setting in its current state. | 974 // Otherwise lock the setting in its current state. |
| 975 var mayChangeOverwrite = !this.editor_.canUndo() && item.isOriginal(); | 975 var mayChangeOverwrite = !this.editor_.canUndo() && item.isOriginal(); |
| 976 ImageUtil.setAttribute(this.options_, 'saved', !mayChangeOverwrite); | 976 ImageUtil.setAttribute(this.options_, 'saved', !mayChangeOverwrite); |
| 977 | 977 |
| 978 if (this.imageView_.getContentRevision() == 1) { // First edit. | 978 if (this.imageView_.getContentRevision() === 1) { // First edit. |
| 979 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('Edit')); | 979 ImageUtil.metrics.recordUserAction(ImageUtil.getMetricName('Edit')); |
| 980 } | 980 } |
| 981 | 981 |
| 982 if (oldUrl != item.getUrl()) { | 982 if (util.isSameEntry(oldEntry, item.getEntry())) { |
| 983 this.dataModel_.splice( | 983 this.dataModel_.splice( |
| 984 this.getSelectedIndex(), 0, new Gallery.Item(oldUrl)); | 984 this.getSelectedIndex(), 0, new Gallery.Item(oldEntry)); |
| 985 // The ribbon will ignore the splice above and redraw after the | 985 // The ribbon will ignore the splice above and redraw after the |
| 986 // select call below (while being obscured by the Editor toolbar, | 986 // select call below (while being obscured by the Editor toolbar, |
| 987 // so there is no need for nice animation here). | 987 // so there is no need for nice animation here). |
| 988 // SlideMode will ignore the selection change as the displayed item | 988 // SlideMode will ignore the selection change as the displayed item |
| 989 // index has not changed. | 989 // index has not changed. |
| 990 this.select(++this.displayedIndex_); | 990 this.select(++this.displayedIndex_); |
| 991 } | 991 } |
| 992 callback(); | 992 callback(); |
| 993 cr.dispatchSimpleEvent(this, 'image-saved'); | 993 cr.dispatchSimpleEvent(this, 'image-saved'); |
| 994 }.bind(this)); | 994 }.bind(this)); |
| 995 }; | 995 }; |
| 996 | 996 |
| 997 /** | 997 /** |
| 998 * Update caches when the selected item url has changed. | 998 * Update caches when the selected item has been renamed. |
| 999 * | |
| 1000 * @param {Event} event Event. | 999 * @param {Event} event Event. |
| 1001 * @private | 1000 * @private |
| 1002 */ | 1001 */ |
| 1003 SlideMode.prototype.onContentChange_ = function(event) { | 1002 SlideMode.prototype.onContentChange_ = function(event) { |
| 1004 var newUrl = event.item.getUrl(); | 1003 var newEntry = event.item.getEntry(); |
| 1005 if (newUrl != event.oldUrl) { | 1004 if (util.isSameEntry(newEntry, event.oldEntry)) |
| 1006 this.imageView_.changeUrl(newUrl); | 1005 this.imageView_.changeEntry(newEntry); |
| 1007 } | 1006 this.metadataCache_.clear(event.oldEntry, Gallery.METADATA_TYPE); |
| 1008 this.metadataCache_.clear(event.oldUrl, Gallery.METADATA_TYPE); | |
| 1009 }; | 1007 }; |
| 1010 | 1008 |
| 1011 /** | 1009 /** |
| 1012 * Flash 'Saved' label briefly to indicate that the image has been saved. | 1010 * Flash 'Saved' label briefly to indicate that the image has been saved. |
| 1013 * @private | 1011 * @private |
| 1014 */ | 1012 */ |
| 1015 SlideMode.prototype.flashSavedLabel_ = function() { | 1013 SlideMode.prototype.flashSavedLabel_ = function() { |
| 1016 var setLabelHighlighted = | 1014 var setLabelHighlighted = |
| 1017 ImageUtil.setAttribute.bind(null, this.savedLabel_, 'highlighted'); | 1015 ImageUtil.setAttribute.bind(null, this.savedLabel_, 'highlighted'); |
| 1018 setTimeout(setLabelHighlighted.bind(null, true), 0); | 1016 setTimeout(setLabelHighlighted.bind(null, true), 0); |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1152 this.leaveAfterSlideshow_ = false; | 1150 this.leaveAfterSlideshow_ = false; |
| 1153 setTimeout(this.toggleMode_.bind(this), toggleModeDelay); | 1151 setTimeout(this.toggleMode_.bind(this), toggleModeDelay); |
| 1154 } | 1152 } |
| 1155 }; | 1153 }; |
| 1156 | 1154 |
| 1157 /** | 1155 /** |
| 1158 * @return {boolean} True if the slideshow is playing (not paused). | 1156 * @return {boolean} True if the slideshow is playing (not paused). |
| 1159 * @private | 1157 * @private |
| 1160 */ | 1158 */ |
| 1161 SlideMode.prototype.isSlideshowPlaying_ = function() { | 1159 SlideMode.prototype.isSlideshowPlaying_ = function() { |
| 1162 return this.container_.getAttribute('slideshow') == 'playing'; | 1160 return this.container_.getAttribute('slideshow') === 'playing'; |
| 1163 }; | 1161 }; |
| 1164 | 1162 |
| 1165 /** | 1163 /** |
| 1166 * Pause/resume the slideshow. | 1164 * Pause/resume the slideshow. |
| 1167 * @private | 1165 * @private |
| 1168 */ | 1166 */ |
| 1169 SlideMode.prototype.toggleSlideshowPause_ = function() { | 1167 SlideMode.prototype.toggleSlideshowPause_ = function() { |
| 1170 cr.dispatchSimpleEvent(this, 'useraction'); // Show the tools. | 1168 cr.dispatchSimpleEvent(this, 'useraction'); // Show the tools. |
| 1171 if (this.isSlideshowPlaying_()) { | 1169 if (this.isSlideshowPlaying_()) { |
| 1172 this.pauseSlideshow_(); | 1170 this.pauseSlideshow_(); |
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1347 done = true; | 1345 done = true; |
| 1348 } | 1346 } |
| 1349 }.bind(this); | 1347 }.bind(this); |
| 1350 }; | 1348 }; |
| 1351 | 1349 |
| 1352 /** | 1350 /** |
| 1353 * If the user touched the image and moved the finger more than SWIPE_THRESHOLD | 1351 * If the user touched the image and moved the finger more than SWIPE_THRESHOLD |
| 1354 * horizontally it's considered as a swipe gesture (change the current image). | 1352 * horizontally it's considered as a swipe gesture (change the current image). |
| 1355 */ | 1353 */ |
| 1356 SwipeOverlay.SWIPE_THRESHOLD = 100; | 1354 SwipeOverlay.SWIPE_THRESHOLD = 100; |
| OLD | NEW |