'use strict';
new ExceptionHandler();
window.app = window.app || {};
app.GooglePhotosPage = Polymer({
is: 'google-photos-page',
behaviors: [
Chrome.LocalizeBehavior,
],
properties: {
isAlbumMode: {
type: Boolean,
value: true,
notify: true,
},
useGoogleAlbums: {
type: Boolean,
value: true,
notify: true,
},
useGooglePhotos: {
type: Boolean,
value: false,
notify: true,
},
albums: {
/** @type {app.GoogleSource.Album[]} */
type: Array,
notify: true,
value: [],
},
selections: {
/** @type {{id: id, photos: photos}} */
type: Array,
value: [],
},
waitForLoad: {
type: Boolean,
value: false,
notify: true,
},
permPicasa: {
type: String,
value: 'notSet',
notify: true,
},
isHidden: {
type: Boolean,
computed: '_computeHidden(waitForLoad, permPicasa)',
},
},
// so we can lazily create the page
factoryImpl: function(id) {
this.setAttribute('id', id);
},
ready: function() {
if (Chrome.Storage.getBool('isAlbumMode')) {
this.loadAlbumList();
}
},
/**
* Query Picasa for the list of the users albums
*/
loadAlbumList: function() {
const ERR_TITLE = Chrome.Locale.localize('err_load_album_list');
this._checkPermissions().then((allowed) => {
if (!allowed) {
const err = new Error(Chrome.Locale.localize('err_auth_picasa'));
return Promise.reject(err);
}
this.set('waitForLoad', true);
return app.GoogleSource.loadAlbumList();
}).then((albums) => {
// get all the user's albums
this.splice('albums', 0, this.albums.length);
albums = albums || [];
albums.forEach((album) => {
this.push('albums', album);
});
// update the currently selected albums from the web
// eslint-disable-next-line promise/no-nesting
app.PhotoSources.process('useGoogleAlbums').catch((err) => {
Chrome.GA.error(err.message, 'GooglePhotosPage.loadAlbumList');
});
// set selected state on albums
this._selectAlbums();
this.set('waitForLoad', false);
return Promise.resolve();
}).catch((err) => {
this.set('waitForLoad', false);
Chrome.Log.error(err.message,
'GooglePhotosPage.loadAlbumList', ERR_TITLE);
this.$.dialogTitle.innerHTML =
Chrome.Locale.localize('err_request_failed');
this.$.dialogText.innerHTML = err.message;
this.$.errorDialog.open();
});
},
/**
* Try to get permissions, if not already authorized - may block
* @returns {Promise<boolean>} true if we have permissions
* @private
*/
_checkPermissions: function() {
if (app.Permissions.isAllowed(app.Permissions.PICASA)) {
return Promise.resolve(true);
} else {
return app.Permissions.request(app.Permissions.PICASA).then((granted) => {
return Promise.resolve(granted);
});
}
},
/**
* Set keys for photo sources
* @param {boolean} useGoogle - Google Photos use enabled
* @param {boolean} isAlbumMode - Are we in album mode
* @private
*/
_setUseKeys: function(useGoogle, isAlbumMode) {
const useAlbums = (useGoogle && isAlbumMode);
const usePhotos = (useGoogle && !isAlbumMode);
this.set('useGoogleAlbums', useAlbums);
this.set('useGooglePhotos', usePhotos);
},
/**
* Event: Handle tap on mode icon
* @private
*/
_onModeTapped: function() {
this.set('isAlbumMode', !this.isAlbumMode);
this._setUseKeys(this.$.googlePhotosToggle.checked, this.isAlbumMode);
if (this.isAlbumMode) {
this.loadAlbumList();
} else {
this.albums.splice(0, this.albums.length);
this.selections.splice(0, this.selections.length);
}
},
/**
* Event: Handle tap on refresh album list icon
* @private
*/
_onRefreshTapped: function() {
Chrome.GA.event(Chrome.GA.EVENT.ICON, 'refreshGoogleAlbums');
this.loadAlbumList();
},
/**
* Event: Handle tap on select all albums icon
* @private
*/
_onSelectAllTapped: function() {
Chrome.GA.event(Chrome.GA.EVENT.ICON, 'selectAllGoogleAlbums');
for (let i = 0; i < this.albums.length; i++) {
const album = this.albums[i];
if (!album.checked) {
this.selections.push({id: album.id, photos: album.photos});
const set = Chrome.Storage.safeSet('albumSelections', this.selections,
'useGoogleAlbums');
if (!set) {
// exceeded storage limits
this.selections.pop();
this._showStorageErrorDialog(
'GooglePhotosPage._onSelectAllTapped');
break;
}
this.set('albums.' + i + '.checked', true);
}
}
},
/**
* Event: Handle tap on deselect all albums icon
* @private
*/
_onDeselectAllTapped: function() {
Chrome.GA.event(Chrome.GA.EVENT.ICON, 'deselectAllGoogleAlbums');
this._uncheckAll();
this.selections.splice(0, this.selections.length);
Chrome.Storage.set('albumSelections', null);
},
/**
* Event: Album checkbox state changed
* @param {Event} event - tap event
* @param {app.GoogleSource.Album} event.model.album - the album
* @private
*/
_onAlbumSelectChanged: function(event) {
const album = event.model.album;
Chrome.GA.event(Chrome.GA.EVENT.CHECK,
`selectGoogleAlbum: ${album.checked}`);
if (album.checked) {
// add new
this.selections.push({id: album.id, photos: album.photos});
} else {
// delete old
const index = this.selections.findIndex((e) => {
return e.id === album.id;
});
if (index !== -1) {
this.selections.splice(index, 1);
}
}
const set = Chrome.Storage.safeSet('albumSelections', this.selections,
'useGoogleAlbums');
if (!set) {
// exceeded storage limits
this.selections.pop();
this.set('albums.' + album.index + '.checked', false);
this._showStorageErrorDialog(
'GooglePhotosPage._onAlbumSelectChanged');
}
},
/**
* Event: checked state changed on main toggle changed
* @private
*/
_onUseGoogleChanged: function() {
const useGoogle = this.$.googlePhotosToggle.checked;
this._setUseKeys(useGoogle, this.isAlbumMode);
Chrome.GA.event(Chrome.GA.EVENT.TOGGLE,
`useGoogle: ${useGoogle}`);
},
/**
* Exceeded storage limits error
* @param {string} method - function that caused error
* @private
*/
_showStorageErrorDialog: function(method) {
const ERR_TITLE = Chrome.Locale.localize('err_storage_title');
Chrome.Log.error('safeSet failed', method, ERR_TITLE);
this.$.dialogTitle.innerHTML = ERR_TITLE;
this.$.dialogText.innerHTML = Chrome.Locale.localize('err_storage_desc');
this.$.errorDialog.open();
},
/**
* Set the checked state of the stored albums
* @private
*/
_selectAlbums: function() {
this.set('selections', Chrome.Storage.get('albumSelections', []));
for (let i = 0; i < this.albums.length; i++) {
for (let j = 0; j < this.selections.length; j++) {
if (this.albums[i].id === this.selections[j].id) {
this.set('albums.' + i + '.checked', true);
break;
}
}
}
},
/**
* Uncheck all albums
* @private
*/
_uncheckAll: function() {
this.albums.forEach((album, index) => {
if (album.checked) {
this.set('albums.' + index + '.checked', false);
}
});
},
/**
* Computed property: Hidden state of main interface
* @param {boolean} waitForLoad - true if loading
* @param {string} permPicasa - permission state
* @returns {boolean} true if hidden
* @private
*/
_computeHidden: function(waitForLoad, permPicasa) {
let ret = true;
if (!waitForLoad && (permPicasa === 'allowed')) {
ret = false;
}
return ret;
},
/**
* Computed binding: Calculate page title
* @param {boolean} isAlbumMode - true if album mode
* @returns {string} page title
* @private
*/
_computeTitle: function(isAlbumMode) {
let ret = '';
if (isAlbumMode) {
ret = Chrome.Locale.localize('google_title');
} else {
ret = Chrome.Locale.localize('google_title_photos');
}
return ret;
},
/**
* Computed binding: Calculate mode icon
* @param {boolean} isAlbumMode - true if album mode
* @returns {string} an icon
* @private
*/
_computeModeIcon: function(isAlbumMode) {
let ret = '';
if (isAlbumMode) {
ret = 'myicons:photo-album';
} else {
ret = 'myicons:photo';
}
return ret;
},
/**
* Computed binding: Calculate mode tooltip
* @param {boolean} isAlbumMode - true if album mode
* @returns {string} page title
* @private
*/
_computeModeTooltip: function(isAlbumMode) {
let ret = '';
if (isAlbumMode) {
ret = Chrome.Locale.localize('tooltip_google_mode_albums');
} else {
ret = Chrome.Locale.localize('tooltip_google_mode_photos');
}
return ret;
},
/**
* Computed binding: Calculate mode tooltip
* @param {boolean} useGoogle - true if using Google Photos
* @param {boolean} isAlbumMode - true if album mode
* @returns {boolean} true if album icons should be disabled
* @private
*/
_computeAlbumIconDisabled(useGoogle, isAlbumMode) {
return !(useGoogle && isAlbumMode);
},
/**
* Computed binding: Set photo count label on an album
* @param {int} count - number of photos in album
* @returns {string} i18n label
* @private
*/
_computePhotoLabel: function(count) {
let ret = `${count} ${Chrome.Locale.localize('photos')}`;
if (count === 1) {
ret = `${count} ${Chrome.Locale.localize('photo')}`;
}
return ret;
},
/**
* Initialize value if it is not in localStorage
* @private
*/
_initPermPicasa: function() {
this.set('permPicasa', 'notSet');
},
/**
* Initialize value if it is not in localStorage
* @private
*/
_initIsAlbumMode: function() {
this.set('isAlbumMode', true);
},
/**
* Initialize value if it is not in localStorage
* @private
*/
_initUseGoogleAlbums: function() {
this.set('useGoogleAlbums', true);
},
/**
* Initialize value if it is not in localStorage
* @private
*/
_initUseGooglePhotos: function() {
this.set('useGooglePhotos', true);
},
});