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