| 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 util.addPageLoadHandler(function() { | 7 util.addPageLoadHandler(function() { |
| 8 if (!location.hash) | 8 if (!location.hash) |
| 9 return; | 9 return; |
| 10 | 10 |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 * @param {boolean=} opt_exiting True if the app is exiting. | 28 * @param {boolean=} opt_exiting True if the app is exiting. |
| 29 */ | 29 */ |
| 30 function unload(opt_exiting) { Gallery.instance.onUnload(opt_exiting) } | 30 function unload(opt_exiting) { Gallery.instance.onUnload(opt_exiting) } |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * Gallery for viewing and editing image files. | 33 * Gallery for viewing and editing image files. |
| 34 * | 34 * |
| 35 * @param {Object} context Object containing the following: | 35 * @param {Object} context Object containing the following: |
| 36 * {function(string)} onNameChange Called every time a selected | 36 * {function(string)} onNameChange Called every time a selected |
| 37 * item name changes (on rename and on selection change). | 37 * item name changes (on rename and on selection change). |
| 38 * {function} onClose | 38 * {function(string)} onBack |
| 39 * {function()} onClose |
| 40 * {function()} onMaximize |
| 39 * {MetadataCache} metadataCache | 41 * {MetadataCache} metadataCache |
| 40 * {Array.<Object>} shareActions | 42 * {Array.<Object>} shareActions |
| 41 * {string} readonlyDirName Directory name for readonly warning or null. | 43 * {string} readonlyDirName Directory name for readonly warning or null. |
| 42 * {DirEntry} saveDirEntry Directory to save to. | 44 * {DirEntry} saveDirEntry Directory to save to. |
| 43 * {function(string)} displayStringFunction. | 45 * {function(string)} displayStringFunction. |
| 44 * @class | 46 * @class |
| 45 * @constructor | 47 * @constructor |
| 46 */ | 48 */ |
| 47 function Gallery(context) { | 49 function Gallery(context) { |
| 48 this.container_ = document.querySelector('.gallery'); | 50 this.container_ = document.querySelector('.gallery'); |
| (...skipping 28 matching lines...) Expand all Loading... |
| 77 * @param {Array.<string>} urls Array of urls. | 79 * @param {Array.<string>} urls Array of urls. |
| 78 * @param {Array.<string>} selectedUrls Array of selected urls. | 80 * @param {Array.<string>} selectedUrls Array of selected urls. |
| 79 */ | 81 */ |
| 80 Gallery.open = function(context, urls, selectedUrls) { | 82 Gallery.open = function(context, urls, selectedUrls) { |
| 81 Gallery.instance = new Gallery(context); | 83 Gallery.instance = new Gallery(context); |
| 82 Gallery.instance.load(urls, selectedUrls); | 84 Gallery.instance.load(urls, selectedUrls); |
| 83 }; | 85 }; |
| 84 | 86 |
| 85 /** | 87 /** |
| 86 * Create a Gallery object in a tab. | 88 * Create a Gallery object in a tab. |
| 89 * TODO(mtomasz): Remove it after dropping support for Files.app V1. |
| 90 * |
| 87 * @param {string} path File system path to a selected file. | 91 * @param {string} path File system path to a selected file. |
| 88 * @param {Object} pageState Page state object. | 92 * @param {Object} pageState Page state object. |
| 89 * @param {function=} opt_callback Called when gallery object is constructed. | 93 * @param {function=} opt_callback Called when gallery object is constructed. |
| 90 */ | 94 */ |
| 91 Gallery.openStandalone = function(path, pageState, opt_callback) { | 95 Gallery.openStandalone = function(path, pageState, opt_callback) { |
| 92 ImageUtil.metrics = metrics; | 96 ImageUtil.metrics = metrics; |
| 93 | 97 |
| 94 var currentDir; | 98 var currentDir; |
| 95 var urls = []; | 99 var urls = []; |
| 96 var selectedUrls = []; | 100 var selectedUrls = []; |
| 97 | 101 |
| 98 Gallery.getFileBrowserPrivate().requestLocalFileSystem(function(filesystem) { | 102 Gallery.getFileBrowserPrivate().requestLocalFileSystem(function(filesystem) { |
| 99 // If the path points to the directory scan it. | 103 // If the path points to the directory scan it. |
| 100 filesystem.root.getDirectory(path, {create: false}, scanDirectory, | 104 filesystem.root.getDirectory(path, {create: false}, scanDirectory, |
| 101 function() { | 105 function() { |
| 102 // Try to scan the parent directory. | 106 // Try to scan the parent directory. |
| 103 var pathParts = path.split('/'); | 107 var pathParts = path.split('/'); |
| 104 pathParts.pop(); | 108 pathParts.pop(); |
| 105 var parentPath = pathParts.join('/'); | 109 var parentPath = pathParts.join('/'); |
| 106 filesystem.root.getDirectory(parentPath, {create: false}, | 110 filesystem.root.getDirectory(parentPath, {create: false}, |
| 107 scanDirectory, open /* no data, just display an error */); | 111 scanDirectory, open /* no data, just display an error */); |
| 108 }); | 112 }); |
| 109 }); | 113 }); |
| 110 | 114 |
| 111 function scanDirectory(dirEntry) { | 115 var scanDirectory = function(dirEntry) { |
| 112 currentDir = dirEntry; | 116 currentDir = dirEntry; |
| 113 util.forEachDirEntry(currentDir, function(entry) { | 117 util.forEachDirEntry(currentDir, function(entry) { |
| 114 if (entry == null) { | 118 if (entry == null) { |
| 115 open(); | 119 open(); |
| 116 } else if (FileType.isImageOrVideo(entry)) { | 120 } else if (FileType.isImageOrVideo(entry)) { |
| 117 var url = entry.toURL(); | 121 var url = entry.toURL(); |
| 118 urls.push(url); | 122 urls.push(url); |
| 119 if (entry.fullPath == path) | 123 if (entry.fullPath == path) |
| 120 selectedUrls = [url]; | 124 selectedUrls = [url]; |
| 121 } | 125 } |
| 122 }); | 126 }); |
| 123 } | 127 }; |
| 124 | 128 |
| 125 function onClose() { | 129 var onBack = function() { |
| 126 // Exiting to the Files app seems arbitrary. Consider closing the tab. | 130 // Exiting to the Files app seems arbitrary. Consider closing the tab. |
| 127 document.location = 'main.html?' + | 131 document.location = 'main.html?' + |
| 128 JSON.stringify({defaultPath: document.location.hash.substr(1)}); | 132 JSON.stringify({defaultPath: document.location.hash.substr(1)}); |
| 129 } | 133 }; |
| 134 |
| 135 var onClose = function() { |
| 136 window.close(); |
| 137 }; |
| 138 |
| 139 var onMaximize = function() { |
| 140 var appWindow = chrome.app.window.current(); |
| 141 if (appWindow.isMaximized()) |
| 142 appWindow.restore(); |
| 143 else |
| 144 appWindow.maximize(); |
| 145 }; |
| 130 | 146 |
| 131 function open() { | 147 function open() { |
| 132 urls.sort(); | 148 urls.sort(); |
| 133 Gallery.getFileBrowserPrivate().getStrings(function(strings) { | 149 Gallery.getFileBrowserPrivate().getStrings(function(strings) { |
| 134 loadTimeData.data = strings; | 150 loadTimeData.data = strings; |
| 135 var context = { | 151 var context = { |
| 136 readonlyDirName: null, | 152 readonlyDirName: null, |
| 137 curDirEntry: currentDir, | 153 curDirEntry: currentDir, |
| 138 saveDirEntry: null, | 154 saveDirEntry: null, |
| 139 metadataCache: MetadataCache.createFull(), | 155 metadataCache: MetadataCache.createFull(), |
| 140 pageState: pageState, | 156 pageState: pageState, |
| 157 onBack: onBack, |
| 141 onClose: onClose, | 158 onClose: onClose, |
| 159 onMaximize: onMaximize, |
| 142 displayStringFunction: strf | 160 displayStringFunction: strf |
| 143 }; | 161 }; |
| 144 Gallery.open(context, urls, selectedUrls); | 162 Gallery.open(context, urls, selectedUrls); |
| 145 if (opt_callback) opt_callback(); | 163 if (opt_callback) opt_callback(); |
| 146 }); | 164 }); |
| 147 } | 165 } |
| 148 }; | 166 }; |
| 149 | 167 |
| 150 /** | 168 /** |
| 151 * Tools fade-out timeout im milliseconds. | 169 * Tools fade-out timeout im milliseconds. |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 | 226 |
| 209 /** | 227 /** |
| 210 * Closes gallery when a volume containing the selected item is unmounted. | 228 * Closes gallery when a volume containing the selected item is unmounted. |
| 211 * @param {Event} event The unmount event. | 229 * @param {Event} event The unmount event. |
| 212 * @private | 230 * @private |
| 213 */ | 231 */ |
| 214 Gallery.prototype.onExternallyUnmounted_ = function(event) { | 232 Gallery.prototype.onExternallyUnmounted_ = function(event) { |
| 215 if (!this.selectedItemFilesystemPath_) | 233 if (!this.selectedItemFilesystemPath_) |
| 216 return; | 234 return; |
| 217 if (this.selectedItemFilesystemPath_.indexOf(event.mountPath) == 0) | 235 if (this.selectedItemFilesystemPath_.indexOf(event.mountPath) == 0) |
| 218 this.onClose_(); | 236 this.onBack_(); |
| 219 }; | 237 }; |
| 220 | 238 |
| 221 /** | 239 /** |
| 222 * Beforeunload handler. | 240 * Beforeunload handler. |
| 223 * @return {string?} User-visible message on null if it is OK to close. | 241 * @return {string?} User-visible message on null if it is OK to close. |
| 224 */ | 242 */ |
| 225 Gallery.prototype.onBeforeUnload = function() { | 243 Gallery.prototype.onBeforeUnload = function() { |
| 226 return this.slideMode_.onBeforeUnload(); | 244 return this.slideMode_.onBeforeUnload(); |
| 227 }; | 245 }; |
| 228 | 246 |
| 229 /** | 247 /** |
| 230 * Unload the Gallery. | 248 * Unload the Gallery. |
| 231 * @param {boolean} exiting True if the app is exiting. | 249 * @param {boolean} exiting True if the app is exiting. |
| 232 */ | 250 */ |
| 233 Gallery.prototype.onUnload = function(exiting) { | 251 Gallery.prototype.onUnload = function(exiting) { |
| 234 if (!this.context_.searchResults) { | 252 if (!this.context_.searchResults) { |
| 235 this.metadataCache_.removeObserver(this.thumbnailObserverId_); | 253 this.metadataCache_.removeObserver(this.thumbnailObserverId_); |
| 236 } | 254 } |
| 237 this.slideMode_.onUnload(exiting); | 255 this.slideMode_.onUnload(exiting); |
| 238 }; | 256 }; |
| 239 | 257 |
| 240 /** | 258 /** |
| 241 * Initializes DOM UI | 259 * Initializes DOM UI |
| 242 * @private | 260 * @private |
| 243 */ | 261 */ |
| 244 Gallery.prototype.initDom_ = function() { | 262 Gallery.prototype.initDom_ = function() { |
| 245 var content = util.createChild(this.container_, 'content'); | 263 var content = util.createChild(this.container_, 'content'); |
| 246 content.addEventListener('click', this.onContentClick_.bind(this)); | 264 content.addEventListener('click', this.onContentClick_.bind(this)); |
| 247 | 265 |
| 248 var closeButton = util.createChild(this.container_, 'close tool dimmable'); | |
| 249 util.createChild(closeButton); | |
| 250 closeButton.addEventListener('click', this.onClose_.bind(this)); | |
| 251 | |
| 252 this.header_ = util.createChild(this.container_, 'header tool dimmable'); | 266 this.header_ = util.createChild(this.container_, 'header tool dimmable'); |
| 253 this.toolbar_ = util.createChild(this.container_, 'toolbar tool dimmable'); | 267 this.toolbar_ = util.createChild(this.container_, 'toolbar tool dimmable'); |
| 254 | 268 |
| 269 var backButton = util.createChild(this.container_, |
| 270 'back-button tool dimmable'); |
| 271 util.createChild(backButton); |
| 272 backButton.addEventListener('click', this.onBack_.bind(this)); |
| 273 |
| 274 if (util.platform.newUI()) { |
| 275 var maximizeButton = util.createChild(this.header_, |
| 276 'maximize-button tool dimmable', |
| 277 'button'); |
| 278 maximizeButton.addEventListener('click', this.onMaximize_.bind(this)); |
| 279 |
| 280 var closeButton = util.createChild(this.header_, |
| 281 'close-button tool dimmable', |
| 282 'button'); |
| 283 closeButton.addEventListener('click', this.onClose_.bind(this)); |
| 284 } |
| 285 |
| 255 this.filenameSpacer_ = util.createChild(this.toolbar_, 'filename-spacer'); | 286 this.filenameSpacer_ = util.createChild(this.toolbar_, 'filename-spacer'); |
| 256 | |
| 257 this.filenameEdit_ = util.createChild(this.filenameSpacer_, | 287 this.filenameEdit_ = util.createChild(this.filenameSpacer_, |
| 258 'namebox', 'input'); | 288 'namebox', 'input'); |
| 259 | 289 |
| 260 this.filenameEdit_.setAttribute('type', 'text'); | 290 this.filenameEdit_.setAttribute('type', 'text'); |
| 261 this.filenameEdit_.addEventListener('blur', | 291 this.filenameEdit_.addEventListener('blur', |
| 262 this.onFilenameEditBlur_.bind(this)); | 292 this.onFilenameEditBlur_.bind(this)); |
| 263 | 293 |
| 264 this.filenameEdit_.addEventListener('focus', | 294 this.filenameEdit_.addEventListener('focus', |
| 265 this.onFilenameFocus_.bind(this)); | 295 this.onFilenameFocus_.bind(this)); |
| 266 | 296 |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 /* TODO: consider nice blow-up animation for the first image */ | 416 /* TODO: consider nice blow-up animation for the first image */ |
| 387 this.slideMode_.enter(null, function() { | 417 this.slideMode_.enter(null, function() { |
| 388 // Flash the toolbar briefly to show it is there. | 418 // Flash the toolbar briefly to show it is there. |
| 389 this.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT); | 419 this.inactivityWatcher_.kick(Gallery.FIRST_FADE_TIMEOUT); |
| 390 }.bind(this), | 420 }.bind(this), |
| 391 maybeLoadMosaic); | 421 maybeLoadMosaic); |
| 392 } | 422 } |
| 393 }; | 423 }; |
| 394 | 424 |
| 395 /** | 425 /** |
| 396 * Close the Gallery. | 426 * Close the Gallery and go to Files.app. |
| 397 * @private | 427 * @private |
| 398 */ | 428 */ |
| 399 Gallery.prototype.close_ = function() { | 429 Gallery.prototype.back_ = function() { |
| 400 if (util.isFullScreen()) { | 430 if (util.isFullScreen()) { |
| 401 util.toggleFullScreen(this.document_, | 431 util.toggleFullScreen(this.document_, |
| 402 false); // Leave the full screen mode. | 432 false); // Leave the full screen mode. |
| 403 } | 433 } |
| 404 this.context_.onClose(this.getSelectedUrls()); | 434 this.context_.onBack(this.getSelectedUrls()); |
| 405 }; | 435 }; |
| 406 | 436 |
| 407 /** | 437 /** |
| 408 * Handle user's 'Close' action (Escape or a click on the X icon). | 438 * Handle user's 'Back' action (Escape or a click on the X icon). |
| 439 * @private |
| 440 */ |
| 441 Gallery.prototype.onBack_ = function() { |
| 442 this.executeWhenReady(this.back_.bind(this)); |
| 443 }; |
| 444 |
| 445 /** |
| 446 * Handle user's 'Close' action. |
| 409 * @private | 447 * @private |
| 410 */ | 448 */ |
| 411 Gallery.prototype.onClose_ = function() { | 449 Gallery.prototype.onClose_ = function() { |
| 412 this.executeWhenReady(this.close_.bind(this)); | 450 this.executeWhenReady(this.context_.onClose); |
| 413 }; | 451 }; |
| 414 | 452 |
| 415 /** | 453 /** |
| 454 * Handle user's 'Maximize' action (Escape or a click on the X icon). |
| 455 * @private |
| 456 */ |
| 457 Gallery.prototype.onMaximize_ = function() { |
| 458 this.executeWhenReady(this.context_.onMaximize); |
| 459 }; |
| 460 |
| 461 /** |
| 416 * Execute a function when the editor is done with the modifications. | 462 * Execute a function when the editor is done with the modifications. |
| 417 * @param {function} callback Function to execute. | 463 * @param {function} callback Function to execute. |
| 418 */ | 464 */ |
| 419 Gallery.prototype.executeWhenReady = function(callback) { | 465 Gallery.prototype.executeWhenReady = function(callback) { |
| 420 this.currentMode_.executeWhenReady(callback); | 466 this.currentMode_.executeWhenReady(callback); |
| 421 }; | 467 }; |
| 422 | 468 |
| 423 /** | 469 /** |
| 424 * @return {Object} File browser private API. | 470 * @return {Object} File browser private API. |
| 425 */ | 471 */ |
| (...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 646 | 692 |
| 647 switch (util.getKeyModifiers(event) + event.keyIdentifier) { | 693 switch (util.getKeyModifiers(event) + event.keyIdentifier) { |
| 648 case 'U+0008': // Backspace. | 694 case 'U+0008': // Backspace. |
| 649 // The default handler would call history.back and close the Gallery. | 695 // The default handler would call history.back and close the Gallery. |
| 650 event.preventDefault(); | 696 event.preventDefault(); |
| 651 break; | 697 break; |
| 652 | 698 |
| 653 case 'U+001B': // Escape | 699 case 'U+001B': // Escape |
| 654 // Swallow Esc if it closed the Share menu, otherwise close the Gallery. | 700 // Swallow Esc if it closed the Share menu, otherwise close the Gallery. |
| 655 if (!wasSharing) | 701 if (!wasSharing) |
| 656 this.onClose_(); | 702 this.onBack_(); |
| 657 break; | 703 break; |
| 658 | 704 |
| 659 case 'U+004D': // 'm' switches between Slide and Mosaic mode. | 705 case 'U+004D': // 'm' switches between Slide and Mosaic mode. |
| 660 this.toggleMode_(null, event); | 706 this.toggleMode_(null, event); |
| 661 break; | 707 break; |
| 662 | 708 |
| 663 | 709 |
| 664 case 'U+0056': // 'v' | 710 case 'U+0056': // 'v' |
| 665 this.slideMode_.startSlideshow(SlideMode.SLIDESHOW_INTERVAL_FIRST, event); | 711 this.slideMode_.startSlideshow(SlideMode.SLIDESHOW_INTERVAL_FIRST, event); |
| 666 return; | 712 return; |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 901 Gallery.prototype.updateThumbnails_ = function() { | 947 Gallery.prototype.updateThumbnails_ = function() { |
| 902 if (this.currentMode_ == this.slideMode_) | 948 if (this.currentMode_ == this.slideMode_) |
| 903 this.slideMode_.updateThumbnails(); | 949 this.slideMode_.updateThumbnails(); |
| 904 | 950 |
| 905 if (this.mosaicMode_) { | 951 if (this.mosaicMode_) { |
| 906 var mosaic = this.mosaicMode_.getMosaic(); | 952 var mosaic = this.mosaicMode_.getMosaic(); |
| 907 if (mosaic.isInitialized()) | 953 if (mosaic.isInitialized()) |
| 908 mosaic.reload(); | 954 mosaic.reload(); |
| 909 } | 955 } |
| 910 }; | 956 }; |
| OLD | NEW |