OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 // Namespace | 5 // Namespace |
6 var importer = importer || {}; | 6 var importer = importer || {}; |
7 | 7 |
8 /** @enum {string} */ | 8 /** @enum {string} */ |
9 importer.ResponseId = { | 9 importer.ResponseId = { |
10 HIDDEN: 'hidden', | 10 HIDDEN: 'hidden', |
(...skipping 18 matching lines...) Expand all Loading... | |
29 * behalf of Cloud Import. | 29 * behalf of Cloud Import. |
30 * | 30 * |
31 * @constructor | 31 * @constructor |
32 * @struct | 32 * @struct |
33 * | 33 * |
34 * @param {!importer.ControllerEnvironment} environment The class providing | 34 * @param {!importer.ControllerEnvironment} environment The class providing |
35 * access to runtime environmental information, like the current directory, | 35 * access to runtime environmental information, like the current directory, |
36 * volume lookup and so-on. | 36 * volume lookup and so-on. |
37 * @param {!importer.MediaScanner} scanner | 37 * @param {!importer.MediaScanner} scanner |
38 * @param {!importer.ImportRunner} importRunner | 38 * @param {!importer.ImportRunner} importRunner |
39 * @param {function()} commandUpdateHandler | 39 * @param {!importer.CommandWidget} commandWidget |
40 */ | 40 */ |
41 importer.ImportController = | 41 importer.ImportController = |
42 function(environment, scanner, importRunner, commandUpdateHandler) { | 42 function(environment, scanner, importRunner, commandWidget) { |
43 | 43 |
44 /** @private {!importer.ControllerEnvironment} */ | 44 /** @private {!importer.ControllerEnvironment} */ |
45 this.environment_ = environment; | 45 this.environment_ = environment; |
46 | 46 |
47 /** @private {!importer.ImportRunner} */ | 47 /** @private {!importer.ImportRunner} */ |
48 this.importRunner_ = importRunner; | 48 this.importRunner_ = importRunner; |
49 | 49 |
50 /** @private {!importer.MediaScanner} */ | 50 /** @private {!importer.MediaScanner} */ |
51 this.scanner_ = scanner; | 51 this.scanner_ = scanner; |
52 | 52 |
53 /** @private {function()} */ | 53 /** @private {!importer.CommandWidget} */ |
54 this.updateCommands_ = commandUpdateHandler; | 54 this.commandWidget_ = commandWidget; |
55 | 55 |
56 /** | 56 /** |
57 * A cache of scans by volumeId, directory URL. | 57 * A cache of scans by volumeId, directory URL. |
58 * Currently only scans of directories are cached. | 58 * Currently only scans of directories are cached. |
59 * @private {!Object.<string, !Object.<string, !importer.ScanResult>>} | 59 * @private {!Object.<string, !Object.<string, !importer.ScanResult>>} |
60 */ | 60 */ |
61 this.cachedScans_ = {}; | 61 this.cachedScans_ = {}; |
62 | 62 |
63 var listener = this.onScanEvent_.bind(this); | 63 var listener = this.onScanEvent_.bind(this); |
64 this.scanner_.addObserver(listener); | 64 this.scanner_.addObserver(listener); |
65 // Remove the observer when the foreground window is closed. | 65 // Remove the observer when the foreground window is closed. |
66 window.addEventListener('pagehide', function() { | 66 window.addEventListener( |
67 this.scanner_.removeObserver(listener); | 67 'pagehide', |
68 }.bind(this)); | 68 function() { |
69 this.scanner_.removeObserver(listener); | |
70 }.bind(this)); | |
71 | |
69 this.environment_.addVolumeUnmountListener( | 72 this.environment_.addVolumeUnmountListener( |
70 this.onVolumeUnmounted_.bind(this)); | 73 this.onVolumeUnmounted_.bind(this)); |
74 | |
71 this.environment_.addDirectoryChangedListener( | 75 this.environment_.addDirectoryChangedListener( |
72 this.onDirectoryChanged_.bind(this)); | 76 this.onDirectoryChanged_.bind(this)); |
77 | |
78 this.commandWidget_.addExecuteListener( | |
79 this.execute.bind(this)); | |
73 }; | 80 }; |
74 | 81 |
75 /** | 82 /** |
76 * @param {!importer.ScanEvent} event Command event. | 83 * @param {!importer.ScanEvent} event Command event. |
77 * @param {importer.ScanResult} result | 84 * @param {importer.ScanResult} result |
78 * | 85 * |
79 * @private | 86 * @private |
80 */ | 87 */ |
81 importer.ImportController.prototype.onScanEvent_ = function(event, result) { | 88 importer.ImportController.prototype.onScanEvent_ = function(event, result) { |
82 if (event === importer.ScanEvent.INVALIDATED) { | 89 if (event === importer.ScanEvent.INVALIDATED) { |
83 for (var key in this.cachedScans_) { | 90 for (var key in this.cachedScans_) { |
84 for (var url in this.cachedScans_[key]) { | 91 for (var url in this.cachedScans_[key]) { |
85 if (this.cachedScans_[key][url].isInvalidated()) { | 92 if (this.cachedScans_[key][url].isInvalidated()) { |
86 delete this.cachedScans_[key][url]; | 93 delete this.cachedScans_[key][url]; |
87 } | 94 } |
88 } | 95 } |
89 } | 96 } |
90 } | 97 } |
91 if (event === importer.ScanEvent.FINALIZED || | 98 if (event === importer.ScanEvent.FINALIZED || |
92 event === importer.ScanEvent.INVALIDATED) { | 99 event === importer.ScanEvent.INVALIDATED) { |
93 this.updateCommands_(); | 100 this.pushUpdate_(); |
94 } | 101 } |
95 }; | 102 }; |
96 | 103 |
97 /** | 104 /** |
98 * Executes import against the current directory. Should only | 105 * Executes import against the current directory. Should only |
99 * be called when the current directory has been validated | 106 * be called when the current directory has been validated |
100 * by calling "update" on this class. | 107 * by calling "update" on this class. |
101 */ | 108 */ |
102 importer.ImportController.prototype.execute = function() { | 109 importer.ImportController.prototype.execute = function() { |
103 metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED'); | 110 metrics.recordEnum('CloudImport.UserAction', 'IMPORT_INITIATED'); |
104 var result = this.getScanForImport_(); | 111 var result = this.getScanForImport_(); |
105 var importTask = this.importRunner_.importFromScanResult(result); | 112 var importTask = this.importRunner_.importFromScanResult(result); |
106 }; | 113 }; |
107 | 114 |
108 /** | 115 /** |
109 * Called by the 'cloud-import' command when it wants an update | 116 * Push an update to the command widget. |
110 * on the command state. | 117 * @private |
118 */ | |
119 importer.ImportController.prototype.pushUpdate_ = function() { | |
120 this.commandWidget_.update(this.getCommandUpdate()); | |
121 }; | |
122 | |
123 /** | |
124 * Returns an update describing the state of the CommandWidget. | |
111 * | 125 * |
112 * @return {!importer.CommandUpdate} response | 126 * @return {!importer.CommandUpdate} response |
113 */ | 127 */ |
114 importer.ImportController.prototype.getCommandUpdate = function() { | 128 importer.ImportController.prototype.getCommandUpdate = function() { |
115 // If there is no Google Drive mount, Drive may be disabled | 129 // If there is no Google Drive mount, Drive may be disabled |
116 // or the machine may be running in guest mode. | 130 // or the machine may be running in guest mode. |
117 if (this.environment_.isGoogleDriveMounted()) { | 131 if (this.environment_.isGoogleDriveMounted()) { |
118 var entries = this.environment_.getSelection(); | 132 var entries = this.environment_.getSelection(); |
119 | 133 |
120 // Enabled if user has a selection and it consists entirely of files | 134 // Enabled if user has a selection and it consists entirely of files |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 | 271 |
258 /** | 272 /** |
259 * @param {string} volumeId | 273 * @param {string} volumeId |
260 * @private | 274 * @private |
261 */ | 275 */ |
262 importer.ImportController.prototype.onVolumeUnmounted_ = function(volumeId) { | 276 importer.ImportController.prototype.onVolumeUnmounted_ = function(volumeId) { |
263 // Forget all scans related to the unmounted volume volume. | 277 // Forget all scans related to the unmounted volume volume. |
264 if (this.cachedScans_.hasOwnProperty(volumeId)) { | 278 if (this.cachedScans_.hasOwnProperty(volumeId)) { |
265 delete this.cachedScans_[volumeId]; | 279 delete this.cachedScans_[volumeId]; |
266 } | 280 } |
281 this.pushUpdate_(); | |
282 }; | |
283 | |
284 /** @private */ | |
285 importer.ImportController.prototype.onDirectoryChanged_ = function() { | |
286 this.pushUpdate_(); | |
267 }; | 287 }; |
268 | 288 |
269 /** | 289 /** |
270 * @param {string} volumeId | |
271 * @private | |
272 */ | |
273 importer.ImportController.prototype.onDirectoryChanged_ = function() { | |
274 this.updateCommands_(); | |
275 }; | |
276 | |
277 /** | |
278 * Interface abstracting away the concrete file manager available | 290 * Interface abstracting away the concrete file manager available |
279 * to commands. By hiding file manager we make it easy to test | 291 * to commands. By hiding file manager we make it easy to test |
280 * ImportController. | 292 * ImportController. |
281 * | 293 * |
282 * @interface | 294 * @interface |
283 * @extends {VolumeManagerCommon.VolumeInfoProvider} | 295 * @extends {VolumeManagerCommon.VolumeInfoProvider} |
284 */ | 296 */ |
285 importer.ControllerEnvironment = function() {}; | 297 importer.ControllerEnvironment = function() {}; |
286 | 298 |
287 /** | 299 /** |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
391 // TODO(smckay): remove listeners when the page is torn down. | 403 // TODO(smckay): remove listeners when the page is torn down. |
392 this.fileManager_.directoryModel.addEventListener( | 404 this.fileManager_.directoryModel.addEventListener( |
393 'directory-changed', | 405 'directory-changed', |
394 listener); | 406 listener); |
395 }; | 407 }; |
396 | 408 |
397 /** | 409 /** |
398 * Class that adapts from the new non-command button to the old | 410 * Class that adapts from the new non-command button to the old |
399 * command style interface. | 411 * command style interface. |
400 * | 412 * |
401 * <p>NOTE: This adapter is a stop gap bridge between the old-style | 413 * @interface |
402 * Command button and our new do-it-yourself toolbar button. We used | 414 */ |
403 * an adapter to minimize changes to RuntimeImportController while other | 415 importer.CommandWidget = function() {}; |
404 * people are working on that file. Once the dust settles we can make | 416 |
405 * more transformative changes. | 417 /** |
418 * Install a listener that get's called when the user wants to initiate | |
419 * import. | |
420 * | |
421 * @param {function()} listener | |
422 */ | |
423 importer.CommandWidget.prototype.addExecuteListener; | |
424 | |
425 /** | |
426 * @param {!importer.CommandUpdate} update | |
427 */ | |
428 importer.CommandWidget.prototype.update; | |
429 | |
430 /** | |
431 * Runtime implementation of CommandWidget. | |
406 * | 432 * |
407 * @constructor | 433 * @constructor |
434 * @implements {importer.CommandWidget} | |
408 * @struct | 435 * @struct |
409 * | |
410 * @param {!FileManager} fileManager | |
411 */ | 436 */ |
412 importer.ButtonCommandAdapter = function(fileManager) { | 437 importer.RuntimeCommandWidget = function() { |
413 | 438 /** @private {Element} */ |
414 /** @param {!FileManager} */ | |
415 this.fileManager_ = fileManager; | |
416 | |
417 /** @param {Element} */ | |
418 this.buttonElement_ = document.querySelector('#cloud-import-button'); | 439 this.buttonElement_ = document.querySelector('#cloud-import-button'); |
419 | 440 |
420 this.buttonElement_.onclick = this.execute_.bind(this); | 441 this.buttonElement_.onclick = this.notifyExecuteListener_.bind(this); |
421 | 442 |
422 /** @param {Element} */ | 443 /** @private {Element} */ |
423 this.iconElement_ = document.querySelector('#cloud-import-button core-icon'); | 444 this.iconElement_ = document.querySelector('#cloud-import-button core-icon'); |
445 | |
446 /** @private {function()} */ | |
447 this.listener_; | |
448 }; | |
449 | |
450 /** @override */ | |
451 importer.RuntimeCommandWidget.prototype.addExecuteListener = | |
452 function(listener) { | |
453 console.assert(!this.listener_); | |
454 this.listener_ = listener; | |
424 }; | 455 }; |
425 | 456 |
426 /** @private */ | 457 /** @private */ |
427 importer.ButtonCommandAdapter.prototype.execute_ = function() { | 458 importer.RuntimeCommandWidget.prototype.notifyExecuteListener_ = function() { |
428 this.fileManager_.importController.execute(); | 459 console.assert(!!this.listener_); |
460 this.listener_(); | |
429 }; | 461 }; |
430 | 462 |
431 /** | 463 /** @override */ |
432 * @param {!Event} event Command event. | 464 importer.RuntimeCommandWidget.prototype.update = function(update) { |
433 * @param {!FileManager} fileManager | |
434 */ | |
435 importer.ButtonCommandAdapter.prototype.update = function() { | |
436 if (this.fileManager_.importController) { | |
437 var update = fileManager.importController.getCommandUpdate(); | |
438 this.buttonElement_.setAttribute('title', update.label); | 465 this.buttonElement_.setAttribute('title', update.label); |
439 this.buttonElement_.disabled = !update.executable; | 466 this.buttonElement_.disabled = !update.executable; |
440 this.buttonElement_.style.display = update.visible ? 'block' : 'none'; | 467 this.buttonElement_.style.display = update.visible ? 'block' : 'none'; |
441 this.iconElement_.setAttribute('icon', update.coreIcon); | 468 this.iconElement_.setAttribute('icon', update.coreIcon); |
442 } else { | |
443 this.buttonElement_.setAttribute('display', 'none'); | |
444 this.iconElement_.setAttribute('icon', 'cloud-off'); | |
445 } | |
446 }; | 469 }; |
470 | |
mtomasz
2015/01/28 22:54:03
nit: remove \n
| |
OLD | NEW |