OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 /** | |
6 * Object representing an image item (a photo or a video). | |
7 * | |
8 * @param {string} url Image url. | |
9 * @constructor | |
10 */ | |
11 Gallery.Item = function(url) { | |
12 this.url_ = url; | |
13 this.original_ = true; | |
14 }; | |
15 | |
16 /** | |
17 * @return {string} Image url. | |
18 */ | |
19 Gallery.Item.prototype.getUrl = function() { return this.url_ }; | |
20 | |
21 /** | |
22 * @param {string} url New url. | |
23 */ | |
24 Gallery.Item.prototype.setUrl = function(url) { this.url_ = url }; | |
25 | |
26 /** | |
27 * @return {string} File name. | |
28 */ | |
29 Gallery.Item.prototype.getFileName = function() { | |
30 return ImageUtil.getFullNameFromUrl(this.url_); | |
dgozman
2012/08/17 07:11:03
I think, we should move this and similar methods t
Vladislav Kaznacheev
2012/08/17 09:20:40
Our numerous *util.js files need a refactoring. Le
dgozman
2012/08/17 09:55:00
100% agree.
| |
31 }; | |
32 | |
33 /** | |
34 * @return {boolean} True if this image has not been created in this session. | |
35 */ | |
36 Gallery.Item.prototype.isOriginal = function() { return this.original_ }; | |
37 | |
38 // TODO: Localize? | |
39 /** | |
40 * @type {string} Prefix for a edited copy file name. | |
41 */ | |
42 Gallery.Item.COPY_SIGNATURE = 'Edited'; | |
43 | |
44 /** | |
45 * Regular exression to match 'Edited - ...'. | |
46 * @type {RegExp} | |
47 */ | |
48 Gallery.Item.REGEXP_COPY_0 = | |
49 new RegExp('^' + Gallery.Item.COPY_SIGNATURE + '( - .+)$'); | |
50 | |
51 /** | |
52 * Regular exression to match 'Edited (N) - ...'. | |
53 * @type {RegExp} | |
54 */ | |
55 Gallery.Item.REGEXP_COPY_N = | |
56 new RegExp('^' + Gallery.Item.COPY_SIGNATURE + ' \\((\\d+)\\)( - .+)$'); | |
57 | |
58 /** | |
59 * Create a name for an edited copy of the file. | |
60 * | |
61 * @param {Entry} dirEntry Entry. | |
62 * @param {function} callback Callback. | |
63 * @private | |
64 */ | |
65 Gallery.Item.prototype.createCopyName_ = function(dirEntry, callback) { | |
66 var name = this.getFileName(); | |
67 | |
68 // If the item represents a file created during the current Gallery session | |
69 // we reuse it for subsequent saves instead of creating multiple copies. | |
70 if (!this.original_) { | |
71 callback(name); | |
72 return; | |
73 } | |
74 | |
75 var ext = ''; | |
76 var index = name.lastIndexOf('.'); | |
77 if (index != -1) { | |
78 ext = name.substr(index); | |
79 name = name.substr(0, index); | |
80 } | |
81 | |
82 if (!ext.match(/jpe?g/i)) { | |
83 // Chrome can natively encode only two formats: JPEG and PNG. | |
84 // All non-JPEG images are saved in PNG, hence forcing the file extension. | |
85 ext = '.png'; | |
86 } | |
87 | |
88 function tryNext(tries) { | |
89 // All the names are used. Let's overwrite the last one. | |
90 if (tries == 0) { | |
91 setTimeout(callback, 0, name + ext); | |
92 return; | |
93 } | |
94 | |
95 // If the file name contains the copy signature add/advance the sequential | |
96 // number. | |
97 var matchN = Gallery.Item.REGEXP_COPY_N.exec(name); | |
98 var match0 = Gallery.Item.REGEXP_COPY_0.exec(name); | |
99 if (matchN && matchN[1] && matchN[2]) { | |
100 var copyNumber = parseInt(matchN[1], 10) + 1; | |
101 name = Gallery.Item.COPY_SIGNATURE + ' (' + copyNumber + ')' + matchN[2]; | |
102 } else if (match0 && match0[1]) { | |
103 name = Gallery.Item.COPY_SIGNATURE + ' (1)' + match0[1]; | |
104 } else { | |
105 name = Gallery.Item.COPY_SIGNATURE + ' - ' + name; | |
106 } | |
107 | |
108 dirEntry.getFile(name + ext, {create: false, exclusive: false}, | |
109 tryNext.bind(null, tries - 1), | |
110 callback.bind(null, name + ext)); | |
111 } | |
112 | |
113 tryNext(10); | |
114 }; | |
115 | |
116 /** | |
117 * Write the new item content to the file. | |
118 * | |
119 * @param {Entry} dirEntry Directory entry. | |
120 * @param {boolean} overwrite True if overwrite, false if copy. | |
121 * @param {HTMLCanvasElement} canvas Source canvas. | |
122 * @param {ImageEncoder.MetadataEncoder} metadataEncoder MetadataEncoder. | |
123 * @param {function(boolean)} opt_callback Callback accepting true for success. | |
124 */ | |
125 Gallery.Item.prototype.saveToFile = function( | |
126 dirEntry, overwrite, canvas, metadataEncoder, opt_callback) { | |
127 ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); | |
128 | |
129 var name = this.getFileName(); | |
dgozman
2012/08/17 07:11:03
We do usually put the code after defining all help
Vladislav Kaznacheev
2012/08/17 09:20:40
Done.
| |
130 if (overwrite) { | |
131 checkExistence(); | |
132 } else { | |
133 this.createCopyName_(dirEntry, function(copyName) { | |
134 this.original_ = false; | |
135 name = copyName; | |
136 checkExistence(); | |
137 }.bind(this)); | |
138 } | |
139 | |
140 var onSuccess = function(url) { | |
141 console.log('Saved from gallery', name); | |
142 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); | |
143 ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); | |
144 this.setUrl(url); | |
145 if (opt_callback) opt_callback(true); | |
146 }.bind(this); | |
147 | |
148 function onError(error) { | |
149 console.log('Error saving from gallery', name, error); | |
150 ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 0, 2); | |
151 if (opt_callback) opt_callback(false); | |
152 } | |
153 | |
154 function doSave(newFile, fileEntry) { | |
155 fileEntry.createWriter(function(fileWriter) { | |
156 function writeContent() { | |
157 fileWriter.onwriteend = onSuccess.bind(null, fileEntry.toURL()); | |
158 fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder)); | |
159 } | |
160 fileWriter.onerror = function(error) { | |
161 onError(error); | |
162 // Disable all callbacks on the first error. | |
163 fileWriter.onerror = null; | |
164 fileWriter.onwriteend = null; | |
165 }; | |
166 if (newFile) { | |
167 writeContent(); | |
168 } else { | |
169 fileWriter.onwriteend = writeContent; | |
170 fileWriter.truncate(0); | |
171 } | |
172 }, onError); | |
173 } | |
174 | |
175 function getFile(newFile) { | |
176 console.log('3', newFile); | |
dgozman
2012/08/17 07:11:03
Debug?
Vladislav Kaznacheev
2012/08/17 09:20:40
Done.
| |
177 dirEntry.getFile(name, {create: newFile, exclusive: newFile}, | |
178 doSave.bind(null, newFile), onError); | |
179 } | |
180 | |
181 function checkExistence() { | |
182 dirEntry.getFile(name, {create: false, exclusive: false}, | |
183 getFile.bind(null, false /* existing file */), | |
184 getFile.bind(null, true /* create new file */)); | |
185 } | |
186 }; | |
187 | |
188 /** | |
189 * Rename the file. | |
190 * | |
191 * @param {Entry} dir Directory entry. | |
192 * @param {string} name New file name. | |
193 * @param {function} onSuccess Success callback. | |
194 * @param {function} onExists Called if the file with the new name exists. | |
195 */ | |
196 Gallery.Item.prototype.rename = function(dir, name, onSuccess, onExists) { | |
197 var oldName = this.getFileName(); | |
198 if (ImageUtil.getExtensionFromFullName(name) == | |
199 ImageUtil.getExtensionFromFullName(oldName)) { | |
200 name = ImageUtil.getFileNameFromFullName(name); | |
201 } | |
202 var newName = ImageUtil.replaceFileNameInFullName(oldName, name); | |
203 if (oldName == newName) return; | |
204 | |
205 function onError() { | |
206 console.log('Rename error: "' + oldName + '" to "' + newName + '"'); | |
207 } | |
208 | |
209 var onRenamed = function(entry) { | |
210 this.setUrl(entry.toURL()); | |
211 onSuccess(); | |
212 }.bind(this); | |
213 | |
214 var doRename = function() { | |
215 dir.getFile( | |
216 this.getFileName(), | |
217 {create: false}, | |
218 function(entry) { entry.moveTo(dir, newName, onRenamed, onError); }, | |
219 onError); | |
220 }.bind(this); | |
221 | |
222 dir.getFile(newName, {create: false, exclusive: false}, onExists, doRename); | |
223 }; | |
OLD | NEW |