15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)'use strict'; 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Object representing an image item (a photo). 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 10a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {FileEntry} entry Image entry. 111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {EntryLocation} locationInfo Entry location information. 121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {Object} metadata Metadata for the entry. 131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {MetadataCache} metadataCache Metadata cache instance. 1403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @param {boolean} original Whether the entry is original or edited. 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @constructor 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGallery.Item = function( 181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci entry, locationInfo, metadata, metadataCache, original) { 19116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 20116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @type {FileEntry} 21116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @private 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.entry_ = entry; 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @type {EntryLocation} 271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @private 281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.locationInfo_ = locationInfo; 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci /** 32116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @type {Object} 33116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @private 34116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 35116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.metadata_ = Object.freeze(metadata); 36116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @type {MetadataCache} 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @private 40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.metadataCache_ = metadataCache; 42116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch /** 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * The content cache is used for prefetching the next image when going through 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * the images sequentially. The real life photos can be large (18Mpix = 72Mb 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * pixel array) so we want only the minimum amount of caching. 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {Canvas} 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.screenImage = null; 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * We reuse previously generated screen-scale images so that going back to a 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * recently loaded image looks instant even if the image is not in the content 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * cache any more. Screen-scale images are small (~1Mpix) so we can afford to 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * cache more of them. 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {Canvas} 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.contentImage = null; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) /** 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Last accessed date to be used for selecting items whose cache are evicted. 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @type {number} 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @private 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.lastAccessed_ = Date.now(); 6603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 6703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) /** 6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @type {boolean} 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) * @private 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) */ 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.original_ = original; 72116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 73116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Object.seal(this); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @return {FileEntry} Image entry. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 79116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.getEntry = function() { return this.entry_; }; 80116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 81116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/** 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @return {EntryLocation} Entry location information. 831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci */ 841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciGallery.Item.prototype.getLocationInfo = function() { 851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return this.locationInfo_; 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}; 871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/** 89116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {Object} Metadata. 90116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 91116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.getMetadata = function() { return this.metadata_; }; 92116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/** 94116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Obtains the latest media metadata. 95116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * 96116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * This is a heavy operation since it forces to load the image data to obtain 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * the metadata. 98116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {Promise} Promise to be fulfilled with fetched metadata. 99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 100116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.getFetchedMedia = function() { 101116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return new Promise(function(fulfill, reject) { 102116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.metadataCache_.getLatest( 103116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch [this.entry_], 104116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 'fetchedMedia', 105116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch function(metadata) { 106116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (metadata[0]) 107116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch fulfill(metadata[0]); 108116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch else 109116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch reject('Failed to load metadata.'); 110116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }); 111116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)); 112116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 113116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 114116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/** 115116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Sets the metadata. 116116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param {Object} metadata New metadata. 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch */ 118116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.setMetadata = function(metadata) { 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.metadata_ = Object.freeze(metadata); 120116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {string} File name. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.prototype.getFileName = function() { 126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) return this.entry_.name; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @return {boolean} True if this image has not been created in this session. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 132116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.isOriginal = function() { return this.original_; }; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Obtains the last accessed date. 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * @return {number} Last accessed date. 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Gallery.Item.prototype.getLastAccessedDate = function() { 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return this.lastAccessed_; 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/** 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Updates the last accessed date. 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */ 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Gallery.Item.prototype.touch = function() { 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) this.lastAccessed_ = Date.now(); 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO: Localize? 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {string} Suffix for a edited copy file name. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.COPY_SIGNATURE = ' - Edited'; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Regular expression to match '... - Edited'. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {RegExp} 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.REGEXP_COPY_0 = 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new RegExp('^(.+)' + Gallery.Item.COPY_SIGNATURE + '$'); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 1634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) * Regular expression to match '... - Edited (N)'. 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @type {RegExp} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.REGEXP_COPY_N = 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new RegExp('^(.+)' + Gallery.Item.COPY_SIGNATURE + ' \\((\\d+)\\)$'); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * Creates a name for an edited copy of the file. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @param {DirectoryEntry} dirEntry Entry. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {function} callback Callback. 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @private 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.prototype.createCopyName_ = function(dirEntry, callback) { 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var name = this.getFileName(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the item represents a file created during the current Gallery session 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // we reuse it for subsequent saves instead of creating multiple copies. 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!this.original_) { 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback(name); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var ext = ''; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var index = name.lastIndexOf('.'); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index != -1) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext = name.substr(index); 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = name.substr(0, index); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ext.match(/jpe?g/i)) { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Chrome can natively encode only two formats: JPEG and PNG. 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All non-JPEG images are saved in PNG, hence forcing the file extension. 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ext = '.png'; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function tryNext(tries) { 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // All the names are used. Let's overwrite the last one. 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tries == 0) { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) setTimeout(callback, 0, name + ext); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the file name contains the copy signature add/advance the sequential 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // number. 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var matchN = Gallery.Item.REGEXP_COPY_N.exec(name); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var match0 = Gallery.Item.REGEXP_COPY_0.exec(name); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (matchN && matchN[1] && matchN[2]) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var copyNumber = parseInt(matchN[2], 10) + 1; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = matchN[1] + Gallery.Item.COPY_SIGNATURE + ' (' + copyNumber + ')'; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (match0 && match0[1]) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = match0[1] + Gallery.Item.COPY_SIGNATURE + ' (1)'; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name += Gallery.Item.COPY_SIGNATURE; 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dirEntry.getFile(name + ext, {create: false, exclusive: false}, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tryNext.bind(null, tries - 1), 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.bind(null, name + ext)); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tryNext(10); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * Writes the new item content to either the existing or a new file. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {VolumeManager} volumeManager Volume manager instance. 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {string} fallbackDir Fallback directory in case the current directory 2321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * is read only. 2331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci * @param {boolean} overwrite Whether to overwrite the image to the item or not. 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {HTMLCanvasElement} canvas Source canvas. 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {ImageEncoder.MetadataEncoder} metadataEncoder MetadataEncoder. 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * @param {function(boolean)=} opt_callback Callback accepting true for success. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Gallery.Item.prototype.saveToFile = function( 2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci volumeManager, fallbackDir, overwrite, canvas, metadataEncoder, 2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci opt_callback) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.startInterval(ImageUtil.getMetricName('SaveTime')); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) var name = this.getFileName(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var onSuccess = function(entry, locationInfo) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 1, 2); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.recordInterval(ImageUtil.getMetricName('SaveTime')); 2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 249a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.entry_ = entry; 2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci this.locationInfo_ = locationInfo; 2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 252116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.metadataCache_.clear([this.entry_], 'fetchedMedia'); 253116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (opt_callback) 254116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch opt_callback(true); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }.bind(this); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var onError = function(error) { 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) console.error('Error saving from gallery', name, error); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ImageUtil.metrics.recordEnum(ImageUtil.getMetricName('SaveResult'), 0, 2); 260116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (opt_callback) 261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch opt_callback(false); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var doSave = function(newFile, fileEntry) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileEntry.createWriter(function(fileWriter) { 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function writeContent() { 267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) fileWriter.onwriteend = onSuccess.bind(null, fileEntry); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.write(ImageEncoder.getBlob(canvas, metadataEncoder)); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.onerror = function(error) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) onError(error); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Disable all callbacks on the first error. 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.onerror = null; 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.onwriteend = null; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (newFile) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) writeContent(); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.onwriteend = writeContent; 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fileWriter.truncate(0); 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, onError); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var getFile = function(dir, newFile) { 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir.getFile(name, {create: newFile, exclusive: newFile}, 2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci function(fileEntry) { 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var locationInfo = volumeManager.getLocationInfo(fileEntry); 2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If the volume is gone, then abort the saving operation. 2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!locationInfo) { 2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci onError('NotFound'); 2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci doSave(newFile, fileEntry, locationInfo); 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }.bind(this), onError); 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci }.bind(this); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci var checkExistence = function(dir) { 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) dir.getFile(name, {create: false, exclusive: false}, 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getFile.bind(null, dir, false /* existing file */), 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) getFile.bind(null, dir, true /* create new file */)); 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) var saveToDir = function(dir) { 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (overwrite && !this.locationInfo_.isReadOnly) { 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checkExistence(dir); 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.createCopyName_(dir, function(copyName) { 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) this.original_ = false; 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name = copyName; 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checkExistence(dir); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }.bind(this)); 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) }.bind(this); 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (this.locationInfo_.isReadOnly) { 31703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) saveToDir(fallbackDir); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 319a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) this.entry_.getParent(saveToDir, onError); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/** 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * Renames the item. 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) * @param {string} displayName New display name (without the extension). 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * @return {Promise} Promise fulfilled with when renaming completes, or rejected 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch * with the error message. 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 330116680a4aac90f2aa7413d9095a592090648e557Ben MurdochGallery.Item.prototype.rename = function(displayName) { 331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch var newFileName = this.entry_.name.replace( 332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ImageUtil.getDisplayNameFromName(this.entry_.name), displayName); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (newFileName === this.entry_.name) 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return Promise.reject('NOT_CHANGED'); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 337116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (/^\s*$/.test(displayName)) 338116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return Promise.reject(str('ERROR_WHITESPACE_NAME')); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var parentDirectoryPromise = new Promise( 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.entry_.getParent.bind(this.entry_)); 342116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return parentDirectoryPromise.then(function(parentDirectory) { 343116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var nameValidatingPromise = 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch util.validateFileName(parentDirectory, newFileName, true); 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return nameValidatingPromise.then(function() { 346116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch var existingFilePromise = new Promise(parentDirectory.getFile.bind( 347116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch parentDirectory, newFileName, {create: false, exclusive: false})); 348116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return existingFilePromise.then(function() { 349116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return Promise.reject(str('GALLERY_FILE_EXISTS')); 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }, function() { 351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return new Promise( 352116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.entry_.moveTo.bind(this.entry_, parentDirectory, newFileName)); 353116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)); 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)); 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)).then(function(entry) { 356116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this.entry_ = entry; 357116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch }.bind(this)); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 359