'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); }, });