OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 // Namespace | |
6 var importer = importer || {}; | |
7 | |
8 /** | |
9 * Handler for importing media from removable devices into the user's Drive. | |
10 * @param {!FileOperationManager} fileOperationManager | |
11 * @param {!MediaScanner=} opt_scanner | |
12 * @constructor | |
13 * @struct | |
14 */ | |
15 importer.MediaImportHandler = function(fileOperationManager, opt_scanner) { | |
16 /** | |
17 * Progress center to submit the progressing item. | |
Steve McKay
2014/12/05 01:09:39
Comment doesn't seem to match the val.
Ben Kwa
2014/12/05 17:22:50
Doh, I completely missed updating this jsdoc. Fix
| |
18 * @private {!FileOperationManager} | |
19 * @const | |
Steve McKay
2014/12/05 01:09:39
Use @const or don't for your "final" fields. Just
Ben Kwa
2014/12/05 17:22:50
Done.
| |
20 */ | |
21 this.fileOperationManager_ = fileOperationManager; | |
22 | |
23 /** @private {!MediaScanner} */ | |
24 this.scanner_ = opt_scanner || new MediaScanner(); | |
25 }; | |
26 | |
27 /** | |
28 * @typedef {function():(!DirectoryEntry|!Promise<!DirectoryEntry>)} | |
29 */ | |
30 importer.MediaImportHandler.DestinationFactory; | |
31 | |
32 /** | |
33 * Import all media found in a given subdirectory tree. | |
34 * @param {!DirectoryEntry} source The directory to import media from. | |
35 * @param {!importer.MediaImportHandler.DestinationFactory=} opt_destination A | |
Steve McKay
2014/12/05 01:09:39
Why not just make opt_destination required, then l
Ben Kwa
2014/12/05 17:22:50
I figured this was a good intermediate step that e
| |
36 * function that returns the directory into which media will be imported. | |
37 * The function will be executed only when the import task actually runs. | |
38 * @return {!importer.MediaImportHandler.ImportTask} The resulting import task. | |
39 */ | |
40 importer.MediaImportHandler.prototype.importMedia = | |
41 function(source, opt_destination) { | |
42 var destination = opt_destination || | |
43 importer.MediaImportHandler.defaultDestination.getImportDestination; | |
44 return new importer.MediaImportHandler.ImportTask( | |
45 this.fileOperationManager_, | |
46 this.scanner_, | |
47 source, | |
48 destination); | |
49 }; | |
50 | |
51 /** | |
52 * Note that this isn't an actual FileOperationManager.Task. It currently uses | |
53 * the FileOperationManager (and thus *spawns* an associated | |
54 * FileOperationManager.CopyTask) but this is a temporary state of affairs. | |
55 * | |
56 * TODO(kenobi): Add a proper implementation that doesn't use | |
57 * FileOperationManager, but instead actually performs the copy using the | |
58 * fileManagerPrivate API directly. | |
59 * | |
60 * @param {!FileOperationManager} fileOperationManager | |
61 * @param {!MediaScanner} mediaScanner | |
62 * @param {!DirectoryEntry} source Source dir containing media for import. | |
63 * @param {!importer.MediaImportHandler.DestinationFactory} destination A | |
64 * function that returns the directory into which media will be imported. | |
65 * @constructor | |
66 * @struct | |
67 */ | |
68 importer.MediaImportHandler.ImportTask = | |
69 function(fileOperationManager, mediaScanner, source, destination) { | |
70 this.source_ = source; | |
Steve McKay
2014/12/05 01:09:39
Missing jsdoc on the fields.
Ben Kwa
2014/12/05 17:22:50
Done.
| |
71 this.scanner_ = mediaScanner; | |
72 | |
73 // Call fileOperationManager.requestTaskCancel to cancel this task. | |
74 // TODO(kenobi): Add task cancellation. | |
75 this.taskId_ = fileOperationManager.generateTaskId(); | |
76 | |
77 Promise.all([ | |
78 destination(), | |
Steve McKay
2014/12/05 01:09:39
I think this is all okay for the early prototype.
Ben Kwa
2014/12/05 17:22:50
I agree with the (eventual) separation between the
| |
79 this.scanner_.scan([source]) | |
80 ]).then( | |
81 function(args) { | |
82 /** @type {!DirectoryEntry} */ | |
83 var destinationDir = args[0]; | |
84 /** @type {!Array<!FileEntry>} */ | |
85 var media = args[1]; | |
86 | |
87 fileOperationManager.paste( | |
88 media, | |
89 destinationDir, | |
90 /* isMove */ false, | |
91 /* opt_taskId */ this.taskId_); | |
92 }.bind(this)); | |
93 }; | |
94 | |
95 /** @struct */ | |
96 importer.MediaImportHandler.ImportTask.prototype = { | |
97 /** | |
98 * @return {string} The task ID. | |
99 */ | |
100 get taskId() { | |
101 return this.taskId_; | |
102 } | |
103 }; | |
104 | |
105 /** | |
106 * Namespace for a default import destination factory. The | |
107 * defaultDestionation.getImportDestination function creates and returns the | |
108 * directory /photos/YYYY-MM-DD in the user's Google Drive. YYYY-MM-DD is the | |
109 * current date. | |
110 */ | |
111 importer.MediaImportHandler.defaultDestination = {}; | |
112 | |
113 /** | |
114 * Retrieves the user's drive root. | |
115 * @return {!Promise<!DirectoryEntry>} | |
116 * @private | |
117 */ | |
118 importer.MediaImportHandler.defaultDestination.getDriveRoot_ = function() { | |
119 // TODO(kenobi): change this to 'other' to get the unparented drive root. | |
120 /** @const {string} */ | |
121 var rootName = 'root'; | |
Steve McKay
2014/12/05 01:09:39
Why not just inline it, or put it in a CONSTANT?
Ben Kwa
2014/12/05 17:22:50
This was here to make it clear what had to change
| |
122 | |
123 return VolumeManager.getInstance() | |
124 .then( | |
125 function(volumeManager) { | |
126 var drive = volumeManager.getCurrentProfileVolumeInfo( | |
127 VolumeManagerCommon.VolumeType.DRIVE); | |
128 // Use the root for unparented objects. | |
129 return new Promise(function(resolve, reject) { | |
hirono
2014/12/05 05:57:37
You can do "return drive.resolveDisplayRoot();"
Ben Kwa
2014/12/05 17:22:50
Thanks! Done.
| |
130 drive.fileSystem.root.getDirectory( | |
131 rootName, | |
132 {create: false}, | |
133 resolve, | |
134 reject); | |
135 }); | |
136 }); | |
137 }; | |
138 | |
139 /** | |
140 * Fetches (creating if necessary) the import destination subdirectory. | |
141 * @param {!DirectoryEntry} root The drive root. | |
142 * @return {!Promise<!DirectoryEntry>} | |
143 * @private | |
144 */ | |
145 importer.MediaImportHandler.defaultDestination.getOrCreateImportDestination_ = | |
146 function(root) { | |
147 /** | |
148 * @param {string} name The name of the new directory. | |
149 * @param {!DirectoryEntry} entry The parent directory. | |
150 * @return {!Promise<!DirectoryEntry>} The created directory. | |
151 */ | |
152 var mkdir_ = function(name, entry) { | |
153 /** @const {Object} */ | |
154 var CREATE_OPTIONS = { | |
155 create: true, | |
156 exclusive: false | |
157 }; | |
158 return new Promise(function(resolve, reject) { | |
159 entry.getDirectory(name, CREATE_OPTIONS, resolve, reject); | |
160 }); | |
161 }; | |
162 | |
163 /** | |
164 * @return {string} The current date, in YYYY-MM-DD format. | |
165 */ | |
166 var getDateString = function() { | |
167 var padAndConvert = function(i) { | |
168 return (i < 10 ? '0' : '') + i.toString(); | |
169 }; | |
170 var date = new Date(); | |
171 var year = date.getFullYear().toString(); | |
172 var month = padAndConvert(date.getMonth()); | |
173 var day = padAndConvert(date.getDate()); | |
174 | |
175 return year + '-' + month + '-' + day; | |
176 }; | |
177 | |
178 return Promise.resolve(root) | |
179 .then(mkdir_.bind(this, 'photos')) | |
180 .then(mkdir_.bind(this, getDateString())); | |
181 }; | |
182 | |
183 /** | |
184 * Returns the destination directory for media imports. Creates the | |
185 * destination, if it doesn't exist. | |
186 * @return {!Promise<!DirectoryEntry>} | |
187 */ | |
188 importer.MediaImportHandler.defaultDestination.getImportDestination = | |
189 function() { | |
190 var defaultDestination = importer.MediaImportHandler.defaultDestination; | |
191 return defaultDestination.getDriveRoot_() | |
192 .then(defaultDestination.getOrCreateImportDestination_); | |
193 }; | |
OLD | NEW |