Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 1 | // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 5 | 'use strict'; |
| 6 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 7 | document.addEventListener('DOMContentLoaded', function() { |
| 8 | ActionChoice.load(); |
| 9 | }); |
| 10 | |
| 11 | /** |
| 12 | * The main ActionChoice object. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 13 | * |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 14 | * @param {HTMLElement} dom Container. |
| 15 | * @param {FileSystem} filesystem Local file system. |
| 16 | * @param {Object} params Parameters. |
| 17 | * @constructor |
| 18 | */ |
| 19 | function ActionChoice(dom, filesystem, params) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 20 | this.dom_ = dom; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 21 | this.filesystem_ = filesystem; |
| 22 | this.params_ = params; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 23 | this.document_ = this.dom_.ownerDocument; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 24 | this.metadataCache_ = this.params_.metadataCache; |
| 25 | this.volumeManager_ = VolumeManager.getInstance(); |
| 26 | this.volumeManager_.addEventListener('externally-unmounted', |
| 27 | this.onDeviceUnmounted_.bind(this)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 28 | this.initDom_(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 29 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 30 | // Load defined actions and remembered choice, then initialize volumes. |
| 31 | this.actions_ = []; |
| 32 | this.actionsById_ = {}; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 33 | this.rememberedChoice_ = null; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 34 | |
| 35 | ActionChoiceUtil.getDefinedActions(loadTimeData, function(actions) { |
| 36 | for (var i = 0; i < actions.length; i++) { |
| 37 | this.registerAction_(actions[i]); |
| 38 | } |
| 39 | |
| 40 | this.viewFilesAction_ = this.actionsById_['view-files']; |
| 41 | this.importPhotosToDriveAction_ = |
| 42 | this.actionsById_['import-photos-to-drive']; |
| 43 | this.watchSingleVideoAction_ = |
| 44 | this.actionsById_['watch-single-video']; |
| 45 | |
| 46 | // Special case: if Google+ Photos is installed, then do not show Drive. |
| 47 | for (var i = 0; i < actions.length; i++) { |
| 48 | if (actions[i].extensionId == ActionChoice.GPLUS_PHOTOS_EXTENSION_ID) { |
| 49 | this.importPhotosToDriveAction_.hidden = true; |
| 50 | break; |
| 51 | } |
| 52 | } |
| 53 | |
| 54 | if (this.params_.advancedMode) { |
| 55 | // In the advanced mode, skip auto-choice. |
| 56 | this.initializeVolumes_(); |
| 57 | } else { |
| 58 | // Get the remembered action before initializing volumes. |
| 59 | ActionChoiceUtil.getRememberedActionId(function(actionId) { |
| 60 | this.rememberedChoice_ = actionId; |
| 61 | this.initializeVolumes_(); |
| 62 | }.bind(this)); |
| 63 | } |
| 64 | this.renderList_(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 65 | }.bind(this)); |
| 66 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 67 | // Try to render, what is already available. |
| 68 | this.renderList_(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 69 | } |
| 70 | |
| 71 | ActionChoice.prototype = { __proto__: cr.EventTarget.prototype }; |
| 72 | |
| 73 | /** |
| 74 | * The number of previews shown. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 75 | * @type {number} |
| 76 | * @const |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 77 | */ |
| 78 | ActionChoice.PREVIEW_COUNT = 3; |
| 79 | |
| 80 | /** |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 81 | * Extension id of Google+ Photos app. |
| 82 | * @type {string} |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 83 | * @const |
| 84 | */ |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 85 | ActionChoice.GPLUS_PHOTOS_EXTENSION_ID = 'efjnaogkjbogokcnohkmnjdojkikgobo'; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 86 | |
| 87 | /** |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 88 | * Loads app in the document body. |
| 89 | * @param {FileSystem=} opt_filesystem Local file system. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 90 | * @param {Object=} opt_params Parameters. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 91 | */ |
| 92 | ActionChoice.load = function(opt_filesystem, opt_params) { |
| 93 | ImageUtil.metrics = metrics; |
| 94 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 95 | var hash = location.hash ? decodeURIComponent(location.hash.substr(1)) : ''; |
| 96 | var query = |
| 97 | location.search ? decodeURIComponent(location.search.substr(1)) : ''; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 98 | var params = opt_params || {}; |
| 99 | if (!params.source) params.source = hash; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 100 | if (!params.advancedMode) params.advancedMode = (query == 'advanced-mode'); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 101 | if (!params.metadataCache) params.metadataCache = MetadataCache.createFull(); |
| 102 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 103 | var onFilesystem = function(filesystem) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 104 | var dom = document.querySelector('.action-choice'); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 105 | ActionChoice.instance = new ActionChoice(dom, filesystem, params); |
| 106 | }; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 107 | |
| 108 | chrome.fileBrowserPrivate.getStrings(function(strings) { |
| 109 | loadTimeData.data = strings; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 110 | i18nTemplate.process(document, loadTimeData); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 111 | if (opt_filesystem) { |
| 112 | onFilesystem(opt_filesystem); |
| 113 | } else { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 114 | chrome.fileBrowserPrivate.requestFileSystem(onFilesystem); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 115 | } |
| 116 | }); |
| 117 | }; |
| 118 | |
| 119 | /** |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 120 | * Registers an action. |
| 121 | * @param {Object} action Action item. |
| 122 | * @private |
| 123 | */ |
| 124 | ActionChoice.prototype.registerAction_ = function(action) { |
| 125 | this.actions_.push(action); |
| 126 | this.actionsById_[action.id] = action; |
| 127 | }; |
| 128 | |
| 129 | /** |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 130 | * Initializes the source and Drive. If the remembered choice is available, |
| 131 | * then performs the action. |
| 132 | * @private |
| 133 | */ |
| 134 | ActionChoice.prototype.initializeVolumes_ = function() { |
| 135 | var checkDriveFinished = false; |
| 136 | var loadSourceFinished = false; |
| 137 | |
| 138 | var maybeRunRememberedAction = function() { |
| 139 | if (!checkDriveFinished || !loadSourceFinished) |
| 140 | return; |
| 141 | |
| 142 | // Run the remembered action if it is available. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 143 | if (this.rememberedChoice_) { |
| 144 | var action = this.actionsById_[this.rememberedChoice_]; |
| 145 | if (action && !action.disabled) |
| 146 | this.runAction_(action); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 147 | } |
| 148 | }.bind(this); |
| 149 | |
| 150 | var onCheckDriveFinished = function() { |
| 151 | checkDriveFinished = true; |
| 152 | maybeRunRememberedAction(); |
| 153 | }; |
| 154 | |
| 155 | var onLoadSourceFinished = function() { |
| 156 | loadSourceFinished = true; |
| 157 | maybeRunRememberedAction(); |
| 158 | }; |
| 159 | |
| 160 | this.checkDrive_(onCheckDriveFinished); |
| 161 | this.loadSource_(this.params_.source, onLoadSourceFinished); |
| 162 | }; |
| 163 | |
| 164 | /** |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 165 | * One-time initialization of dom elements. |
| 166 | * @private |
| 167 | */ |
| 168 | ActionChoice.prototype.initDom_ = function() { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 169 | this.list_ = new cr.ui.List(); |
| 170 | this.list_.id = 'actions-list'; |
| 171 | this.document_.querySelector('.choices').appendChild(this.list_); |
| 172 | |
| 173 | var self = this; // .bind(this) doesn't work on constructors. |
| 174 | this.list_.itemConstructor = function(item) { |
| 175 | return self.renderItem(item); |
| 176 | }; |
| 177 | |
| 178 | this.list_.selectionModel = new cr.ui.ListSingleSelectionModel(); |
| 179 | this.list_.dataModel = new cr.ui.ArrayDataModel([]); |
| 180 | this.list_.autoExpands = true; |
| 181 | |
| 182 | var acceptActionBound = function() { |
| 183 | this.acceptAction_(); |
| 184 | }.bind(this); |
| 185 | this.list_.activateItemAtIndex = acceptActionBound; |
| 186 | this.list_.addEventListener('click', acceptActionBound); |
| 187 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 188 | this.previews_ = this.document_.querySelector('.previews'); |
| 189 | this.counter_ = this.document_.querySelector('.counter'); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 190 | this.document_.addEventListener('keydown', this.onKeyDown_.bind(this)); |
| 191 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 192 | metrics.startInterval('PhotoImport.Load'); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 193 | this.dom_.setAttribute('loading', ''); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 194 | }; |
| 195 | |
| 196 | /** |
| 197 | * Renders the list. |
| 198 | * @private |
| 199 | */ |
| 200 | ActionChoice.prototype.renderList_ = function() { |
| 201 | var currentItem = this.list_.dataModel.item( |
| 202 | this.list_.selectionModel.selectedIndex); |
| 203 | |
| 204 | this.list_.startBatchUpdates(); |
| 205 | this.list_.dataModel.splice(0, this.list_.dataModel.length); |
| 206 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 207 | for (var i = 0; i < this.actions_.length; i++) { |
| 208 | if (!this.actions_[i].hidden) |
| 209 | this.list_.dataModel.push(this.actions_[i]); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 210 | } |
| 211 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 212 | for (var i = 0; i < this.list_.dataModel.length; i++) { |
| 213 | if (this.list_.dataModel.item(i) == currentItem) { |
| 214 | this.list_.selectionModel.selectedIndex = i; |
| 215 | break; |
| 216 | } |
| 217 | } |
| 218 | |
| 219 | this.list_.endBatchUpdates(); |
| 220 | }; |
| 221 | |
| 222 | /** |
| 223 | * Renders an item in the list. |
| 224 | * @param {Object} item Item to render. |
| 225 | * @return {Element} DOM element with representing the item. |
| 226 | */ |
| 227 | ActionChoice.prototype.renderItem = function(item) { |
| 228 | var result = this.document_.createElement('li'); |
| 229 | |
| 230 | var div = this.document_.createElement('div'); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 231 | if (item.disabled && item.disabledTitle) |
| 232 | div.textContent = item.disabledTitle; |
| 233 | else |
| 234 | div.textContent = item.title; |
| 235 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 236 | if (item.class) |
| 237 | div.classList.add(item.class); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 238 | if (item.icon100 && item.icon200) |
| 239 | div.style.backgroundImage = '-webkit-image-set(' + |
| 240 | 'url(' + item.icon100 + ') 1x,' + |
| 241 | 'url(' + item.icon200 + ') 2x)'; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 242 | if (item.disabled) |
| 243 | div.classList.add('disabled'); |
| 244 | |
| 245 | cr.defineProperty(result, 'lead', cr.PropertyKind.BOOL_ATTR); |
| 246 | cr.defineProperty(result, 'selected', cr.PropertyKind.BOOL_ATTR); |
| 247 | result.appendChild(div); |
| 248 | |
| 249 | return result; |
| 250 | }; |
| 251 | |
| 252 | /** |
| 253 | * Checks whether Drive is reachable. |
| 254 | * |
| 255 | * @param {function()} callback Completion callback. |
| 256 | * @private |
| 257 | */ |
| 258 | ActionChoice.prototype.checkDrive_ = function(callback) { |
| 259 | var onMounted = function() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 260 | this.importPhotosToDriveAction_.disabled = false; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 261 | this.renderList_(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 262 | callback(); |
| 263 | }.bind(this); |
| 264 | |
| 265 | if (this.volumeManager_.isMounted(RootDirectory.DRIVE)) { |
| 266 | onMounted(); |
| 267 | } else { |
| 268 | this.volumeManager_.mountDrive(onMounted, callback); |
| 269 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 270 | }; |
| 271 | |
| 272 | /** |
| 273 | * Load the source contents. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 274 | * |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 275 | * @param {string} source Path to source. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 276 | * @param {function()} callback Completion callback. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 277 | * @private |
| 278 | */ |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 279 | ActionChoice.prototype.loadSource_ = function(source, callback) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 280 | var onTraversed = function(results) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 281 | metrics.recordInterval('PhotoImport.Scan'); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 282 | var videos = results.filter(FileType.isVideo); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 283 | if (videos.length == 1) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 284 | this.singleVideo_ = videos[0]; |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 285 | this.watchSingleVideoAction_.title = loadTimeData.getStringF( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 286 | 'ACTION_CHOICE_WATCH_SINGLE_VIDEO', videos[0].name); |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 287 | this.watchSingleVideoAction_.hidden = false; |
| 288 | this.watchSingleVideoAction_.disabled = false; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 289 | this.renderList_(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 290 | } |
| 291 | |
| 292 | var mediaFiles = results.filter(FileType.isImageOrVideo); |
| 293 | if (mediaFiles.length == 0) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 294 | // If we have no media files, the only choice is view files. So, don't |
| 295 | // confuse user with a single choice, and just open file manager. |
| 296 | this.viewFiles_(); |
| 297 | this.recordAction_('view-files-auto'); |
| 298 | this.close_(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 299 | } |
| 300 | |
| 301 | if (mediaFiles.length < ActionChoice.PREVIEW_COUNT) { |
| 302 | this.counter_.textContent = loadTimeData.getStringF( |
| 303 | 'ACTION_CHOICE_COUNTER_NO_MEDIA', results.length); |
| 304 | } else { |
| 305 | this.counter_.textContent = loadTimeData.getStringF( |
| 306 | 'ACTION_CHOICE_COUNTER', mediaFiles.length); |
| 307 | } |
| 308 | var previews = mediaFiles.length ? mediaFiles : results; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 309 | var previewsCount = Math.min(ActionChoice.PREVIEW_COUNT, previews.length); |
| 310 | this.renderPreview_(previews, previewsCount); |
| 311 | callback(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 312 | }.bind(this); |
| 313 | |
| 314 | var onEntry = function(entry) { |
| 315 | this.sourceEntry_ = entry; |
| 316 | this.document_.querySelector('title').textContent = entry.name; |
| 317 | |
| 318 | var deviceType = this.volumeManager_.getDeviceType(entry.fullPath); |
| 319 | if (deviceType != 'sd') deviceType = 'usb'; |
| 320 | this.dom_.querySelector('.device-type').setAttribute('device-type', |
| 321 | deviceType); |
| 322 | this.dom_.querySelector('.loading-text').textContent = |
| 323 | loadTimeData.getString('ACTION_CHOICE_LOADING_' + |
| 324 | deviceType.toUpperCase()); |
| 325 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 326 | util.traverseTree(entry, onTraversed, 0 /* infinite depth */, |
| 327 | FileType.isVisible); |
| 328 | }.bind(this); |
| 329 | |
| 330 | var onReady = function() { |
| 331 | util.resolvePath(this.filesystem_.root, source, onEntry, function() { |
| 332 | this.recordAction_('error'); |
| 333 | this.close_(); |
| 334 | }.bind(this)); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 335 | }.bind(this); |
| 336 | |
| 337 | this.sourceEntry_ = null; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 338 | metrics.startInterval('PhotoImport.Scan'); |
| 339 | if (!this.volumeManager_.isReady()) |
| 340 | this.volumeManager_.addEventListener('ready', onReady); |
| 341 | else |
| 342 | onReady(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 343 | }; |
| 344 | |
| 345 | /** |
| 346 | * Renders a preview for a media entry. |
| 347 | * @param {Array.<FileEntry>} entries The entries. |
| 348 | * @param {number} count Remaining count. |
| 349 | * @private |
| 350 | */ |
| 351 | ActionChoice.prototype.renderPreview_ = function(entries, count) { |
| 352 | var entry = entries.shift(); |
| 353 | var box = this.document_.createElement('div'); |
| 354 | box.className = 'img-container'; |
| 355 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 356 | var done = function() { |
| 357 | this.dom_.removeAttribute('loading'); |
| 358 | metrics.recordInterval('PhotoImport.Load'); |
| 359 | }.bind(this); |
| 360 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 361 | var onSuccess = function() { |
| 362 | this.previews_.appendChild(box); |
| 363 | if (--count == 0) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 364 | done(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 365 | } else { |
| 366 | this.renderPreview_(entries, count); |
| 367 | } |
| 368 | }.bind(this); |
| 369 | |
| 370 | var onError = function() { |
| 371 | if (entries.length == 0) { |
| 372 | // Append one image with generic thumbnail. |
| 373 | this.previews_.appendChild(box); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 374 | done(); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 375 | } else { |
| 376 | this.renderPreview_(entries, count); |
| 377 | } |
| 378 | }.bind(this); |
| 379 | |
| 380 | this.metadataCache_.get(entry, 'thumbnail|filesystem', |
| 381 | function(metadata) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 382 | new ThumbnailLoader(entry.toURL(), |
| 383 | ThumbnailLoader.LoaderType.IMAGE, |
| 384 | metadata).load( |
| 385 | box, |
| 386 | ThumbnailLoader.FillMode.FILL, |
| 387 | ThumbnailLoader.OptimizationMode.NEVER_DISCARD, |
| 388 | onSuccess, |
| 389 | onError, |
| 390 | onError); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 391 | }); |
| 392 | }; |
| 393 | |
| 394 | /** |
| 395 | * Closes the window. |
| 396 | * @private |
| 397 | */ |
| 398 | ActionChoice.prototype.close_ = function() { |
| 399 | window.close(); |
| 400 | }; |
| 401 | |
| 402 | /** |
| 403 | * Keydown event handler. |
| 404 | * @param {Event} e The event. |
| 405 | * @private |
| 406 | */ |
| 407 | ActionChoice.prototype.onKeyDown_ = function(e) { |
| 408 | switch (util.getKeyModifiers(e) + e.keyCode) { |
| 409 | case '13': |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 410 | this.acceptAction_(); |
| 411 | break; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 412 | case '27': |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 413 | this.recordAction_('close'); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 414 | this.close_(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 415 | break; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 416 | } |
| 417 | }; |
| 418 | |
| 419 | /** |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 420 | * Runs an action. |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 421 | * @param {Object} action Action item to perform. |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 422 | * @private |
| 423 | */ |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 424 | ActionChoice.prototype.runAction_ = function(action) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 425 | // TODO(mtomasz): Remove these predefined actions in Apps v2. |
| 426 | if (action == this.importPhotosToDriveAction_) { |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 427 | var url = chrome.runtime.getURL('photo_import.html') + |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 428 | '#' + this.sourceEntry_.fullPath; |
| 429 | var width = 728; |
| 430 | var height = 656; |
| 431 | var top = Math.round((window.screen.availHeight - height) / 2); |
| 432 | var left = Math.round((window.screen.availWidth - width) / 2); |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 433 | chrome.app.window.create(url, |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 434 | {height: height, width: width, left: left, top: top}); |
| 435 | this.recordAction_('import-photos-to-drive'); |
| 436 | this.close_(); |
| 437 | return; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 438 | } |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 439 | |
| 440 | if (action == this.watchSingleVideoAction_) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 441 | chrome.fileBrowserPrivate.viewFiles([this.singleVideo_.toURL()], |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 442 | function(success) {}); |
| 443 | this.recordAction_('watch-single-video'); |
| 444 | this.close_(); |
| 445 | return; |
| 446 | } |
| 447 | |
| 448 | if (action == this.viewFilesAction_) { |
| 449 | this.viewFiles_(); |
| 450 | this.recordAction_('view-files'); |
| 451 | this.close_(); |
| 452 | return; |
| 453 | } |
| 454 | |
| 455 | if (!action.extensionId) { |
| 456 | console.error('Unknown predefined action.'); |
| 457 | return; |
| 458 | } |
| 459 | |
| 460 | // Run the media galleries handler. |
| 461 | chrome.mediaGalleriesPrivate.launchHandler(action.extensionId, |
| 462 | action.actionId, |
| 463 | this.params_.source); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 464 | this.close_(); |
| 465 | }; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 466 | |
| 467 | /** |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 468 | * Handles accepting an action. Checks if the action is available, remembers |
| 469 | * and runs it. |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 470 | * @private |
| 471 | */ |
| 472 | ActionChoice.prototype.acceptAction_ = function() { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 473 | var action = |
| 474 | this.list_.dataModel.item(this.list_.selectionModel.selectedIndex); |
| 475 | if (!action || action.hidden || action.disabled) |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 476 | return; |
| 477 | |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 478 | this.runAction_(action); |
| 479 | ActionChoiceUtil.setRememberedActionId(action.id); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 480 | }; |
| 481 | |
| 482 | /** |
| 483 | * Called when some device is unmounted. |
| 484 | * @param {Event} event Event object. |
| 485 | * @private |
| 486 | */ |
| 487 | ActionChoice.prototype.onDeviceUnmounted_ = function(event) { |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 488 | if (this.sourceEntry_ && event.mountPath == this.sourceEntry_.fullPath) |
| 489 | window.close(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 490 | }; |
| 491 | |
| 492 | /** |
| 493 | * Perform the 'view files' action. |
| 494 | * @private |
| 495 | */ |
| 496 | ActionChoice.prototype.viewFiles_ = function() { |
| 497 | var path = this.sourceEntry_.fullPath; |
Torne (Richard Coles) | 7d4cd47 | 2013-06-19 11:58:07 +0100 | [diff] [blame] | 498 | chrome.runtime.getBackgroundPage(function(bg) { |
| 499 | bg.launchFileManager({defaultPath: path}); |
| 500 | }); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 501 | }; |
| 502 | |
| 503 | /** |
| 504 | * Records an action chosen. |
| 505 | * @param {string} action Action name. |
| 506 | * @private |
| 507 | */ |
| 508 | ActionChoice.prototype.recordAction_ = function(action) { |
| 509 | metrics.recordEnum('PhotoImport.Action', action, |
| 510 | ['import-photos-to-drive', |
| 511 | 'view-files', |
| 512 | 'view-files-auto', |
| 513 | 'watch-single-video', |
| 514 | 'error', |
| 515 | 'close']); |
| 516 | }; |