Commit b7b13868 authored by Wenzhao Zang's avatar Wenzhao Zang Committed by Commit Bot

cros: Fetch daily refresh image from Backdrop service

1) The new wallpaper picker relies on the Backdrop server to select
   surprise me images, instead of selecting random images by ourseleves
   (the back-end was implemented by a prior CL).

2) The surprise me images are per-category, ie. each wallpaper category
   has a "daily refresh slider". At most one slider may be active at
   a time. Toggling one slider to active should deactivate others.

3) Use "daily refresh" instead of "surprise me" in the code to
   distinguish from the old picker. Although it's possible to share
   code path with the old picker, generally avoid it for clarity.

Test steps include:
1) Toggle daily refresh between enabled/disabled, during
   tablet/clamshell mode, and among different categories.
2) Enable surprise me on the old picker, then add switch
   --new-wallpaper-picker, and see the migration.
3) See the sync is working for two devices with the same account id.

Bug: 834998, 810169, 834994, 837338
Change-Id: I369ce57ac4bd07e91da31bb2971b6970501f9c3a
Reviewed-on: https://chromium-review.googlesource.com/1093742
Commit-Queue: Wenzhao (Colin) Zang <wzang@chromium.org>
Reviewed-by: default avatarXiaoqian Dai <xdai@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568732}
parent 26d1c8e8
...@@ -623,6 +623,10 @@ body.v2 { ...@@ -623,6 +623,10 @@ body.v2 {
color: rgb(32, 33, 36); color: rgb(32, 33, 36);
} }
.v2.daily-wallpaper .top-header-contents #wallpaper-description {
max-width: 226px;
}
.v2 .top-header-contents .more-options { .v2 .top-header-contents .more-options {
display: flex; display: flex;
position: absolute; position: absolute;
...@@ -635,6 +639,7 @@ html[dir='rtl'] .v2 .top-header-contents .more-options { ...@@ -635,6 +639,7 @@ html[dir='rtl'] .v2 .top-header-contents .more-options {
} }
.v2 .top-header-contents .more-options > div { .v2 .top-header-contents .more-options > div {
background-color: #fff;
border: 0.5px solid; border: 0.5px solid;
border-color: rgba(128, 134, 139, 0.6); border-color: rgba(128, 134, 139, 0.6);
border-radius: 16px; border-radius: 16px;
...@@ -699,8 +704,17 @@ html[dir='rtl'] .v2 .top-header-contents .more-options { ...@@ -699,8 +704,17 @@ html[dir='rtl'] .v2 .top-header-contents .more-options {
-webkit-margin-start: 96px; -webkit-margin-start: 96px;
} }
.v2.daily-wallpaper .top-header-contents #confirm-preview-wallpaper {
-webkit-margin-start: 8px;
}
.v2 .top-header-contents #refresh-wallpaper {
-webkit-margin-start: 16px;
}
.v2.preview-mode.custom-wallpaper .more-options .custom-option, .v2.preview-mode.custom-wallpaper .more-options .custom-option,
.v2.preview-mode:not(.custom-wallpaper) .more-options :not(.custom-option) { .v2.preview-mode.daily-wallpaper .more-options .daily-option,
.v2.preview-mode:not(.custom-wallpaper):not(.daily-option) .more-options :not(.custom-option):not(.daily-option) {
display: flex; display: flex;
} }
......
...@@ -25,7 +25,8 @@ ...@@ -25,7 +25,8 @@
AccessSyncWallpaperInfoKey: 'wallpaper-sync-info-key', AccessSyncWallpaperInfoKey: 'wallpaper-sync-info-key',
/** /**
* Key to access last changed date of a surprise wallpaper in * Key to access last changed date of a surprise me wallpaper (on the old
* picker) or a daily refresh wallpaper (on the new picker) in
* chrome.storage.local or chrome.storage.sync. * chrome.storage.local or chrome.storage.sync.
*/ */
AccessLastSurpriseWallpaperChangedDate: 'wallpaper-last-changed-date-key', AccessLastSurpriseWallpaperChangedDate: 'wallpaper-last-changed-date-key',
...@@ -42,6 +43,18 @@ ...@@ -42,6 +43,18 @@
*/ */
AccessSyncSurpriseMeEnabledKey: 'sync-surprise-me-enabled-key', AccessSyncSurpriseMeEnabledKey: 'sync-surprise-me-enabled-key',
/**
* Key to access the info related to daily refresh feature (on the new
* wallpaper picker) in chrome.storage.local.
*/
AccessLocalDailyRefreshInfoKey: 'daily-refresh-info-key',
/**
* Key to access the info related to daily refresh feature (on the new
* wallpaper picker) in chrome.storage.sync.
*/
AccessSyncDailyRefreshInfoKey: 'sync-daily-refresh-info-key',
/** /**
* URL to get latest wallpaper RSS feed. * URL to get latest wallpaper RSS feed.
*/ */
......
...@@ -207,45 +207,62 @@ SurpriseWallpaper.prototype.setRandomWallpaperFromManifest_ = function( ...@@ -207,45 +207,62 @@ SurpriseWallpaper.prototype.setRandomWallpaperFromManifest_ = function(
*/ */
SurpriseWallpaper.prototype.setRandomWallpaperFromServer_ = function( SurpriseWallpaper.prototype.setRandomWallpaperFromServer_ = function(
onSuccess, suffix) { onSuccess, suffix) {
// The first step is to get the list of wallpaper collections (ie. categories) var onDailyRefreshInfoReturned = dailyRefreshInfo => {
// and randomly select one. var setRandomWallpaperFromServerImpl = dailyRefreshInfo => {
chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => { chrome.wallpaperPrivate.getSurpriseMeImage(
if (chrome.runtime.lastError) { dailyRefreshInfo.collectionId, dailyRefreshInfo.resumeToken,
this.retryLater_(); (imageInfo, nextResumeToken) => {
return; if (chrome.runtime.lastError) {
} this.retryLater_();
if (collectionsInfo.length == 0) { return;
// Although the fetch succeeds, it's theoretically possible that the }
// collection list is empty, in this case do nothing. dailyRefreshInfo.resumeToken = nextResumeToken;
WallpaperUtil.saveDailyRefreshInfo(dailyRefreshInfo);
var wallpaperUrl = imageInfo['imageUrl'] + suffix;
var layout = Constants.WallpaperThumbnailDefaultLayout;
WallpaperUtil.setOnlineWallpaperWithoutPreview(
wallpaperUrl, layout,
onSuccess.bind(null, wallpaperUrl, layout),
this.retryLater_.bind(this));
});
};
if (dailyRefreshInfo) {
if (dailyRefreshInfo.enabled) {
setRandomWallpaperFromServerImpl(dailyRefreshInfo);
} else {
console.error(
'Daily refresh is disabled when the alarm goes off. ' +
'This should never happen!');
}
return; return;
} }
var randomCollectionIndex = // Migration: we reach here if the old picker set an alarm and by the time
Math.floor(Math.random() * collectionsInfo.length); // the alarm goes off, the new picker is already in use. We should ensure
var collectionId = collectionsInfo[randomCollectionIndex]['collectionId']; // the user transitions to the daily refresh feature.
// The second step is to get the list of wallpapers that belong to the chrome.wallpaperPrivate.getCollectionsInfo(collectionsInfo => {
// particular collection, and randomly select one.
chrome.wallpaperPrivate.getImagesInfo(collectionId, imagesInfo => {
if (chrome.runtime.lastError) { if (chrome.runtime.lastError) {
this.retryLater_(); this.retryLater_();
return; return;
} }
if (imagesInfo.length == 0) { if (collectionsInfo.length == 0) {
// Although the fetch succeeds, it's theoretically possible that the // Although the fetch succeeds, it's theoretically possible that the
// image list is empty, in this case do nothing. // collection list is empty, in this case do nothing.
// TODO(crbug.com/800945): Consider fetching another collection.
return; return;
} }
var randomImageIndex = Math.floor(Math.random() * imagesInfo.length); dailyRefreshInfo = {
var wallpaperUrl = imagesInfo[randomImageIndex]['imageUrl'] + suffix; enabled: true,
// The backend service doesn't specify the desired layout. Use the default // Use the first collection (an arbitrary choice).
// layout here. collectionId: collectionsInfo[0]['collectionId'],
var layout = Constants.WallpaperThumbnailDefaultLayout; resumeToken: null
WallpaperUtil.setOnlineWallpaperWithoutPreview( };
wallpaperUrl, layout, onSuccess.bind(null, wallpaperUrl, layout), setRandomWallpaperFromServerImpl(dailyRefreshInfo);
this.retryLater_.bind(this));
}); });
}); };
WallpaperUtil.getDailyRefreshInfo(onDailyRefreshInfoReturned.bind(null));
}; };
/** /**
...@@ -401,6 +418,30 @@ chrome.syncFileSystem.onFileStatusChanged.addListener(function(detail) { ...@@ -401,6 +418,30 @@ chrome.syncFileSystem.onFileStatusChanged.addListener(function(detail) {
chrome.storage.onChanged.addListener(function(changes, namespace) { chrome.storage.onChanged.addListener(function(changes, namespace) {
WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) { WallpaperUtil.enabledSyncThemesCallback(function(syncEnabled) {
// Daily refresh feature is on the new wallpaper picker only.
var updateDailyRefreshStates = key => {
if (!changes[key])
return;
var oldDailyRefreshInfo = JSON.parse(changes[key].oldValue);
var newDailyRefreshInfo = JSON.parse(changes[key].newValue);
// The resume token is expected to change after a new daily refresh
// wallpaper is set. Ignore it if it's the only change.
if (oldDailyRefreshInfo.enabled === newDailyRefreshInfo.enabled &&
oldDailyRefreshInfo.collectionId ===
newDailyRefreshInfo.collectionId) {
return;
}
// Although the old and new values may both have enabled == true, they can
// have different collection ids, so the old alarm should always be
// cleared.
chrome.alarms.clearAll();
if (newDailyRefreshInfo.enabled)
SurpriseWallpaper.getInstance().next();
};
updateDailyRefreshStates(
syncEnabled ? Constants.AccessSyncDailyRefreshInfoKey :
Constants.AccessLocalDailyRefreshInfoKey);
if (syncEnabled) { if (syncEnabled) {
// If sync theme is enabled, use values from chrome.storage.sync to sync // If sync theme is enabled, use values from chrome.storage.sync to sync
// wallpaper changes. // wallpaper changes.
...@@ -462,12 +503,14 @@ chrome.storage.onChanged.addListener(function(changes, namespace) { ...@@ -462,12 +503,14 @@ chrome.storage.onChanged.addListener(function(changes, namespace) {
wpDocument.querySelector('.check').style.visibility = wpDocument.querySelector('.check').style.visibility =
'visible'; 'visible';
} }
wpDocument.querySelector('#categories-list').disabled = enable;
chrome.commandLinePrivate.hasSwitch( chrome.commandLinePrivate.hasSwitch(
'new-wallpaper-picker', useNewWallpaperPicker => { 'new-wallpaper-picker', useNewWallpaperPicker => {
if (!useNewWallpaperPicker) if (!useNewWallpaperPicker) {
wpDocument.querySelector('#wallpaper-grid').disabled = wpDocument.querySelector('#wallpaper-grid').disabled =
enable; enable;
wpDocument.querySelector('#categories-list').disabled =
enable;
}
}); });
}); });
} }
......
...@@ -500,3 +500,71 @@ WallpaperUtil.testSendMessage = function(message) { ...@@ -500,3 +500,71 @@ WallpaperUtil.testSendMessage = function(message) {
if (test) if (test)
test.sendMessage(message); test.sendMessage(message);
}; };
/**
* Gets the daily refresh info from sync storage, or local storage if the former
* is not available.
* @param {function} callback A callback that takes the value of the info, or
* null if the value is invalid.
*/
WallpaperUtil.getDailyRefreshInfo = function(callback) {
WallpaperUtil.enabledSyncThemesCallback(syncEnabled => {
var parseInfo = dailyRefreshInfoJson => {
if (!dailyRefreshInfoJson) {
callback(null);
return;
}
var dailyRefreshInfo = JSON.parse(dailyRefreshInfoJson);
if (!dailyRefreshInfo.hasOwnProperty('enabled') ||
!dailyRefreshInfo.hasOwnProperty('collectionId') ||
!dailyRefreshInfo.hasOwnProperty('resumeToken')) {
callback(null);
return;
}
callback(dailyRefreshInfo);
};
if (syncEnabled) {
Constants.WallpaperSyncStorage.get(
Constants.AccessSyncDailyRefreshInfoKey, items => {
var dailyRefreshInfoJson =
items[Constants.AccessSyncDailyRefreshInfoKey];
if (dailyRefreshInfoJson) {
parseInfo(dailyRefreshInfoJson);
} else {
Constants.WallpaperLocalStorage.get(
Constants.AccessLocalDailyRefreshInfoKey, items => {
dailyRefreshInfoJson =
items[Constants.AccessLocalDailyRefreshInfoKey];
parseInfo(dailyRefreshInfoJson);
if (dailyRefreshInfoJson) {
WallpaperUtil.saveToSyncStorage(
Constants.AccessSyncDailyRefreshInfoKey,
dailyRefreshInfoJson);
}
});
}
});
} else {
Constants.WallpaperLocalStorage.get(
Constants.AccessLocalDailyRefreshInfoKey, items => {
parseInfo(items[Constants.AccessLocalDailyRefreshInfoKey]);
});
}
});
};
/**
* Saves the daily refresh info to local and sync storage.
* @param {Object} dailyRefreshInfo The daily refresh info.
*/
WallpaperUtil.saveDailyRefreshInfo = function(dailyRefreshInfo) {
var dailyRefreshInfoJson = JSON.stringify(dailyRefreshInfo);
WallpaperUtil.saveToLocalStorage(
Constants.AccessLocalDailyRefreshInfoKey, dailyRefreshInfoJson,
null /*opt_callback=*/);
WallpaperUtil.saveToSyncStorage(
Constants.AccessSyncDailyRefreshInfoKey, dailyRefreshInfoJson,
null /*opt_callback=*/);
};
...@@ -387,6 +387,15 @@ cr.define('wallpapers', function() { ...@@ -387,6 +387,15 @@ cr.define('wallpapers', function() {
{}; {};
}, },
/**
* The id of the collection that the wallpapers belong to, assuming all the
* wallpapers have the same id (enfored by the source of the data model).
* @type {string}
*/
get collectionId() {
return this.dataModel.item(this.dataModel.length - 1).collectionId;
},
/** /**
* A unique ID that assigned to each set dataModel operation. Note that this * A unique ID that assigned to each set dataModel operation. Note that this
* id wont increase if the new dataModel is null or empty. * id wont increase if the new dataModel is null or empty.
...@@ -697,11 +706,9 @@ cr.define('wallpapers', function() { ...@@ -697,11 +706,9 @@ cr.define('wallpapers', function() {
if (!this.dailyRefreshItem.querySelector('.daily-refresh-banner')) { if (!this.dailyRefreshItem.querySelector('.daily-refresh-banner')) {
var dailyRefreshBanner = document.querySelector('.daily-refresh-banner') var dailyRefreshBanner = document.querySelector('.daily-refresh-banner')
.cloneNode(true /*deep=*/); .cloneNode(true /*deep=*/);
dailyRefreshBanner.querySelector('.daily-refresh-slider') wallpaperManager.decorateDailyRefreshSlider(
.addEventListener( this.collectionId,
'click', dailyRefreshBanner.querySelector('.daily-refresh-slider'));
WallpaperManager.prototype.toggleSurpriseMe.bind(
wallpaperManager));
this.dailyRefreshItem.appendChild(dailyRefreshBanner); this.dailyRefreshItem.appendChild(dailyRefreshBanner);
} }
......
...@@ -55,6 +55,14 @@ function WallpaperManager(dialogDom) { ...@@ -55,6 +55,14 @@ function WallpaperManager(dialogDom) {
this.imagesInfoMap_ = {}; this.imagesInfoMap_ = {};
// The total count of images whose info has been fetched. // The total count of images whose info has been fetched.
this.imagesInfoCount_ = 0; this.imagesInfoCount_ = 0;
// |dailyRefreshInfo_| stores the info related to the daily refresh feature
// on the new picker. Its value should be consistent with the sync/local
// storage.
this.dailyRefreshInfo_ = null;
// |pendingDailyRefreshInfo_| stores the up-to-date daily refresh info that
// hasn't been confirmed by user (e.g. when user is previewing the image).
// Its value will either replace |dailyRefreshInfo_| or be discarded.
this.pendingDailyRefreshInfo_ = null;
this.placeWallpaperPicker_(); this.placeWallpaperPicker_();
$('spinner').hidden = false; $('spinner').hidden = false;
this.getCollectionsInfo_(); this.getCollectionsInfo_();
...@@ -246,12 +254,15 @@ WallpaperManager.prototype.getCollectionsInfo_ = function() { ...@@ -246,12 +254,15 @@ WallpaperManager.prototype.getCollectionsInfo_ = function() {
// Use the next available unique id. // Use the next available unique id.
wallpaperId: this.imagesInfoCount_, wallpaperId: this.imagesInfoCount_,
baseURL: imagesInfo[i]['imageUrl'], baseURL: imagesInfo[i]['imageUrl'],
highResolutionURL:
imagesInfo[i]['imageUrl'] + str('highResolutionSuffix'),
layout: Constants.WallpaperThumbnailDefaultLayout, layout: Constants.WallpaperThumbnailDefaultLayout,
source: Constants.WallpaperSourceEnum.Online, source: Constants.WallpaperSourceEnum.Online,
availableOffline: false, availableOffline: false,
displayText: imagesInfo[i]['displayText'], displayText: imagesInfo[i]['displayText'],
authorWebsite: imagesInfo[i]['actionUrl'], authorWebsite: imagesInfo[i]['actionUrl'],
collectionName: this.collectionsInfo_[index]['collectionName'] collectionName: this.collectionsInfo_[index]['collectionName'],
collectionId: collectionId
}; };
wallpapersDataModel.push(wallpaperInfo); wallpapersDataModel.push(wallpaperInfo);
++this.imagesInfoCount_; ++this.imagesInfoCount_;
...@@ -309,10 +320,8 @@ WallpaperManager.prototype.placeWallpaperPicker_ = function() { ...@@ -309,10 +320,8 @@ WallpaperManager.prototype.placeWallpaperPicker_ = function() {
// Wallpaper preview must always be in full screen. Exit preview if the // Wallpaper preview must always be in full screen. Exit preview if the
// window is not in full screen for any reason (e.g. when device locks). // window is not in full screen for any reason (e.g. when device locks).
if (!chrome.app.window.current().isFullscreen() && if (!chrome.app.window.current().isFullscreen() && this.isDuringPreview_())
this.document_.body.classList.contains('preview-mode')) {
$('cancel-preview-wallpaper').click(); $('cancel-preview-wallpaper').click();
}
var totalWidth = this.document_.body.offsetWidth; var totalWidth = this.document_.body.offsetWidth;
var totalHeight = this.document_.body.offsetHeight; var totalHeight = this.document_.body.offsetHeight;
...@@ -500,7 +509,9 @@ WallpaperManager.prototype.postDownloadDomInit_ = function() { ...@@ -500,7 +509,9 @@ WallpaperManager.prototype.postDownloadDomInit_ = function() {
} }
}); });
if (this.enableOnlineWallpaper_) { this.initializeDailyRefreshStates_();
if (this.enableOnlineWallpaper_ && !this.useNewWallpaperPicker_) {
this.document_.body.setAttribute('surprise-me-disabled', ''); this.document_.body.setAttribute('surprise-me-disabled', '');
$('surprise-me').hidden = false; $('surprise-me').hidden = false;
$('surprise-me') $('surprise-me')
...@@ -542,7 +553,9 @@ WallpaperManager.prototype.postDownloadDomInit_ = function() { ...@@ -542,7 +553,9 @@ WallpaperManager.prototype.postDownloadDomInit_ = function() {
}); });
} }
}); });
}
if (this.enableOnlineWallpaper_) {
window.addEventListener('offline', () => { window.addEventListener('offline', () => {
$('wallpaper-grid').classList.add('image-picker-offline'); $('wallpaper-grid').classList.add('image-picker-offline');
if (this.useNewWallpaperPicker_) { if (this.useNewWallpaperPicker_) {
...@@ -738,28 +751,40 @@ WallpaperManager.prototype.decorateCurrentWallpaperInfoBar_ = function() { ...@@ -738,28 +751,40 @@ WallpaperManager.prototype.decorateCurrentWallpaperInfoBar_ = function() {
(isOnlineWallpaper, isFromOldPicker) => { (isOnlineWallpaper, isFromOldPicker) => {
// Initialize the "more options" buttons. // Initialize the "more options" buttons.
var isOnlineWallpaper = !!currentWallpaperInfo; var isOnlineWallpaper = !!currentWallpaperInfo;
var surpriseMeEnabled =
!this.document_.body.hasAttribute('surprise-me-disabled');
var visibleItemList = []; var visibleItemList = [];
$('refresh').hidden = !surpriseMeEnabled; $('refresh').hidden = !isOnlineWallpaper || !this.dailyRefreshInfo_ ||
!this.dailyRefreshInfo_.enabled;
if (!$('refresh').hidden) { if (!$('refresh').hidden) {
$('refresh').parentNode.replaceChild(
$('refresh').cloneNode(true), $('refresh'));
visibleItemList.push($('refresh')); visibleItemList.push($('refresh'));
// TODO(wzang): Add event listener to this button. $('refresh').addEventListener('click', () => {
this.pendingDailyRefreshInfo_ = this.dailyRefreshInfo_;
this.setDailyRefreshWallpaper_();
});
} }
$('explore').hidden = !isOnlineWallpaper; $('explore').hidden = !isOnlineWallpaper;
if (!$('explore').hidden) { if (!$('explore').hidden) {
visibleItemList.push($('explore')); visibleItemList.push($('explore'));
$('current-wallpaper-explore-link').href = $('current-wallpaper-explore-link').href =
currentWallpaperInfo.authorWebsite; currentWallpaperInfo.authorWebsite;
} }
$('center').hidden = isOnlineWallpaper || surpriseMeEnabled;
$('center').hidden = isOnlineWallpaper;
if (!$('center').hidden) { if (!$('center').hidden) {
$('center').parentNode.replaceChild(
$('center').cloneNode(true), $('center'));
visibleItemList.push($('center')); visibleItemList.push($('center'));
$('center').addEventListener( $('center').addEventListener(
'click', this.setCustomWallpaperLayout_.bind(this, 'CENTER')); 'click', this.setCustomWallpaperLayout_.bind(this, 'CENTER'));
} }
$('center-cropped').hidden = isOnlineWallpaper || surpriseMeEnabled;
$('center-cropped').hidden = isOnlineWallpaper;
if (!$('center-cropped').hidden) { if (!$('center-cropped').hidden) {
$('center-cropped')
.parentNode.replaceChild(
$('center-cropped').cloneNode(true), $('center-cropped'));
visibleItemList.push($('center-cropped')); visibleItemList.push($('center-cropped'));
$('center-cropped') $('center-cropped')
.addEventListener( .addEventListener(
...@@ -980,7 +1005,22 @@ WallpaperManager.prototype.setSelectedWallpaper_ = function(selectedItem) { ...@@ -980,7 +1005,22 @@ WallpaperManager.prototype.setSelectedWallpaper_ = function(selectedItem) {
this.onWallpaperChanged_(selectedItem, selectedItem.baseURL); this.onWallpaperChanged_(selectedItem, selectedItem.baseURL);
break; break;
case Constants.WallpaperSourceEnum.Online: case Constants.WallpaperSourceEnum.Online:
this.setSelectedOnlineWallpaper_(selectedItem); var previewMode = this.shouldPreviewWallpaper_();
var successCallback = () => {
if (previewMode) {
this.onPreviewModeStarted_(
Constants.WallpaperSourceEnum.Online,
this.onWallpaperChanged_.bind(
this, selectedItem, selectedItem.highResolutionURL),
/*optCancelCallback=*/null, /*optOnRefreshClicked=*/null);
} else {
this.onWallpaperChanged_(
selectedItem, selectedItem.highResolutionURL);
}
};
this.setSelectedOnlineWallpaper_(
selectedItem, successCallback, /*optFailureCallback=*/null,
previewMode);
break; break;
case Constants.WallpaperSourceEnum.Daily: case Constants.WallpaperSourceEnum.Daily:
case Constants.WallpaperSourceEnum.ThirdParty: case Constants.WallpaperSourceEnum.ThirdParty:
...@@ -1067,7 +1107,8 @@ WallpaperManager.prototype.setCustomWallpaperSelectedOnNewPicker_ = function( ...@@ -1067,7 +1107,8 @@ WallpaperManager.prototype.setCustomWallpaperSelectedOnNewPicker_ = function(
this.onPreviewModeStarted_( this.onPreviewModeStarted_(
Constants.WallpaperSourceEnum.Custom, Constants.WallpaperSourceEnum.Custom,
successCallback.bind(null, imageData, optThumbnailData), successCallback.bind(null, imageData, optThumbnailData),
null /*optCancelCallback=*/); /*optCancelCallback=*/null,
/*optOnRefreshClicked=*/null);
} }
}); });
}); });
...@@ -1117,16 +1158,15 @@ WallpaperManager.prototype.setCustomWallpaperSelectedOnOldPicker_ = function( ...@@ -1117,16 +1158,15 @@ WallpaperManager.prototype.setCustomWallpaperSelectedOnOldPicker_ = function(
* Implementation of |setSelectedWallpaper_| for online wallpapers. * Implementation of |setSelectedWallpaper_| for online wallpapers.
* @param {Object} selectedItem The selected item in WallpaperThumbnailsGrid's * @param {Object} selectedItem The selected item in WallpaperThumbnailsGrid's
* data model. * data model.
* @param {function} successCallback The callback after the wallpaper is set
* successfully.
* @param {function} optFailureCallback The optional callback after setting the
* wallpaper fails.
* @param {boolean} previewMode True if the wallpaper should be previewed.
* @private
*/ */
WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function( WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
selectedItem) { selectedItem, successCallback, optFailureCallback, previewMode) {
if (selectedItem.source != Constants.WallpaperSourceEnum.Online) {
console.error(
'|setSelectedOnlineWallpaper_| is called but the wallpaper source is ' +
'not online.');
return;
}
// Cancel any ongoing wallpaper request, otherwise the wallpaper being set in // Cancel any ongoing wallpaper request, otherwise the wallpaper being set in
// the end may not be the one that the user selected the last, because the // the end may not be the one that the user selected the last, because the
// time needed to set each wallpaper may vary (e.g. some wallpapers already // time needed to set each wallpaper may vary (e.g. some wallpapers already
...@@ -1136,23 +1176,12 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function( ...@@ -1136,23 +1176,12 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
this.wallpaperRequest_ = null; this.wallpaperRequest_ = null;
} }
var wallpaperUrl = selectedItem.baseURL + str('highResolutionSuffix'); var wallpaperUrl = selectedItem.highResolutionURL ?
selectedItem.highResolutionURL :
selectedItem.baseURL + str('highResolutionSuffix');
var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem); var selectedGridItem = this.wallpaperGrid_.getListItem(selectedItem);
var previewMode = this.shouldPreviewWallpaper_();
chrome.wallpaperPrivate.setWallpaperIfExists( chrome.wallpaperPrivate.setWallpaperIfExists(
wallpaperUrl, selectedItem.layout, previewMode, exists => { wallpaperUrl, selectedItem.layout, previewMode, exists => {
var successCallback = () => {
if (previewMode) {
this.onPreviewModeStarted_(
Constants.WallpaperSourceEnum.Online,
this.onWallpaperChanged_.bind(this, selectedItem, wallpaperUrl),
null /*optCancelCallback=*/);
} else {
this.onWallpaperChanged_(selectedItem, wallpaperUrl);
}
};
if (exists) { if (exists) {
successCallback(); successCallback();
return; return;
...@@ -1176,6 +1205,8 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function( ...@@ -1176,6 +1205,8 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
// likely due to a decode failure) from a download // likely due to a decode failure) from a download
// failure. // failure.
this.showError_(str('downloadFailed')); this.showError_(str('downloadFailed'));
if (optFailureCallback)
optFailureCallback();
} else { } else {
successCallback(); successCallback();
} }
...@@ -1186,6 +1217,8 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function( ...@@ -1186,6 +1217,8 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
this.progressManager_.hideProgressBar(selectedGridItem); this.progressManager_.hideProgressBar(selectedGridItem);
this.showError_(str('downloadFailed')); this.showError_(str('downloadFailed'));
this.wallpaperRequest_ = null; this.wallpaperRequest_ = null;
if (optFailureCallback)
optFailureCallback();
}; };
WallpaperUtil.fetchURL( WallpaperUtil.fetchURL(
wallpaperUrl, 'arraybuffer', onSuccess, onFailure, wallpaperUrl, 'arraybuffer', onSuccess, onFailure,
...@@ -1201,11 +1234,13 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function( ...@@ -1201,11 +1234,13 @@ WallpaperManager.prototype.setSelectedOnlineWallpaper_ = function(
* wallpaper is set. * wallpaper is set.
* @param {function} optCancelCallback The callback after preview * @param {function} optCancelCallback The callback after preview
* is canceled. * is canceled.
* @param {function} optOnRefreshClicked The event listener for the refresh
* button. Must be non-null when the wallpaper type is daily.
* @private * @private
*/ */
WallpaperManager.prototype.onPreviewModeStarted_ = function( WallpaperManager.prototype.onPreviewModeStarted_ = function(
source, optConfirmCallback, optCancelCallback) { source, optConfirmCallback, optCancelCallback, optOnRefreshClicked) {
if (this.document_.body.classList.contains('preview-mode')) if (this.isDuringPreview_())
return; return;
this.document_.body.classList.add('preview-animation'); this.document_.body.classList.add('preview-animation');
...@@ -1215,6 +1250,8 @@ WallpaperManager.prototype.onPreviewModeStarted_ = function( ...@@ -1215,6 +1250,8 @@ WallpaperManager.prototype.onPreviewModeStarted_ = function(
this.document_.body.classList.add('preview-mode'); this.document_.body.classList.add('preview-mode');
this.document_.body.classList.toggle( this.document_.body.classList.toggle(
'custom-wallpaper', source == Constants.WallpaperSourceEnum.Custom); 'custom-wallpaper', source == Constants.WallpaperSourceEnum.Custom);
this.document_.body.classList.toggle(
'daily-wallpaper', source == Constants.WallpaperSourceEnum.Daily);
}, 800); }, 800);
var onConfirmClicked = () => { var onConfirmClicked = () => {
...@@ -1226,9 +1263,16 @@ WallpaperManager.prototype.onPreviewModeStarted_ = function( ...@@ -1226,9 +1263,16 @@ WallpaperManager.prototype.onPreviewModeStarted_ = function(
}; };
$('confirm-preview-wallpaper').addEventListener('click', onConfirmClicked); $('confirm-preview-wallpaper').addEventListener('click', onConfirmClicked);
var onRefreshClicked = () => {
if (optOnRefreshClicked)
optOnRefreshClicked();
};
$('refresh-wallpaper').addEventListener('click', onRefreshClicked);
var onCancelClicked = () => { var onCancelClicked = () => {
$('confirm-preview-wallpaper') $('confirm-preview-wallpaper')
.removeEventListener('click', onConfirmClicked); .removeEventListener('click', onConfirmClicked);
$('refresh-wallpaper').removeEventListener('click', onRefreshClicked);
$('cancel-preview-wallpaper').removeEventListener('click', onCancelClicked); $('cancel-preview-wallpaper').removeEventListener('click', onCancelClicked);
chrome.wallpaperPrivate.cancelPreviewWallpaper(() => { chrome.wallpaperPrivate.cancelPreviewWallpaper(() => {
if (optCancelCallback) if (optCancelCallback)
...@@ -1680,7 +1724,8 @@ WallpaperManager.prototype.setCustomWallpaperLayout_ = function(newLayout) { ...@@ -1680,7 +1724,8 @@ WallpaperManager.prototype.setCustomWallpaperLayout_ = function(newLayout) {
this.onPreviewModeStarted_( this.onPreviewModeStarted_(
Constants.WallpaperSourceEnum.Custom, null /*optConfirmCallback=*/, Constants.WallpaperSourceEnum.Custom, null /*optConfirmCallback=*/,
setCustomWallpaperLayoutImpl.bind( setCustomWallpaperLayoutImpl.bind(
null, this.currentWallpaperLayout_)); null, this.currentWallpaperLayout_),
/*optOnRefreshClicked=*/null);
}); });
}); });
}; };
...@@ -1702,17 +1747,11 @@ WallpaperManager.prototype.setCustomWallpaperLayout_ = function(newLayout) { ...@@ -1702,17 +1747,11 @@ WallpaperManager.prototype.setCustomWallpaperLayout_ = function(newLayout) {
WallpaperManager.prototype.onSurpriseMeStateChanged_ = function(enabled) { WallpaperManager.prototype.onSurpriseMeStateChanged_ = function(enabled) {
WallpaperUtil.setSurpriseMeCheckboxValue(enabled); WallpaperUtil.setSurpriseMeCheckboxValue(enabled);
$('categories-list').disabled = enabled; $('categories-list').disabled = enabled;
$('wallpaper-grid').disabled = enabled;
if (enabled) if (enabled)
this.document_.body.removeAttribute('surprise-me-disabled'); this.document_.body.removeAttribute('surprise-me-disabled');
else else
this.document_.body.setAttribute('surprise-me-disabled', ''); this.document_.body.setAttribute('surprise-me-disabled', '');
// The surprise me state affects the UI of the current wallpaper info bar.
this.decorateCurrentWallpaperInfoBar_();
// On the old wallpaper picker, the wallpaper grid should be disabled when
// surprise me is enabled.
if (!this.useNewWallpaperPicker_)
$('wallpaper-grid').disabled = enabled;
}; };
/** /**
...@@ -1909,6 +1948,15 @@ WallpaperManager.prototype.shouldPreviewWallpaper_ = function() { ...@@ -1909,6 +1948,15 @@ WallpaperManager.prototype.shouldPreviewWallpaper_ = function() {
chrome.app.window.current().isMaximized()); chrome.app.window.current().isMaximized());
}; };
/**
* Returns whether preview mode is currently on.
* @return {boolean} Whether preview mode is currently on.
* @private
*/
WallpaperManager.prototype.isDuringPreview_ = function() {
return this.document_.body.classList.contains('preview-mode');
};
/** /**
* Notifies the wallpaper manager that the scroll bar position changes. * Notifies the wallpaper manager that the scroll bar position changes.
* @param {number} scrollTop The distance between the scroll bar and the top. * @param {number} scrollTop The distance between the scroll bar and the top.
...@@ -1947,4 +1995,197 @@ WallpaperManager.prototype.toggleLayoutButtonStates_ = function(layout) { ...@@ -1947,4 +1995,197 @@ WallpaperManager.prototype.toggleLayoutButtonStates_ = function(layout) {
$('center-cropped').classList.toggle('disabled', layout == 'CENTER_CROPPED'); $('center-cropped').classList.toggle('disabled', layout == 'CENTER_CROPPED');
}; };
/**
* Fetches the info related to the daily refresh feature and updates the UI for
* the sliders. Only used by the new wallpaper picker.
* @private
*/
WallpaperManager.prototype.initializeDailyRefreshStates_ = function() {
if (!this.useNewWallpaperPicker_)
return;
var initializeDailyRefreshStatesImpl = dailyRefreshInfo => {
if (dailyRefreshInfo) {
this.dailyRefreshInfo_ = dailyRefreshInfo;
} else {
// We reach here if it's the first time the new picker is in use, or the
// unlikely case that the data was corrupted (it's safe to assume daily
// refresh is disabled if this ever happens).
this.dailyRefreshInfo_ = {
enabled: false,
collectionId: null,
resumeToken: null
};
}
this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
this.decorateCurrentWallpaperInfoBar_();
};
WallpaperUtil.getDailyRefreshInfo(
initializeDailyRefreshStatesImpl.bind(null));
};
/**
* Updates the UI of all the daily refresh sliders based on the info.
* @param {Object} dailyRefreshInfo The daily refresh info.
* @private
*/
WallpaperManager.prototype.updateDailyRefreshSliderStates_ = function(
dailyRefreshInfo) {
if (!this.dailyRefreshSliderMap_ || !dailyRefreshInfo)
return;
Object.entries(this.dailyRefreshSliderMap_)
.forEach(([collectionId, dailyRefreshSlider]) => {
var enabled = dailyRefreshInfo.enabled &&
dailyRefreshInfo.collectionId === collectionId;
dailyRefreshSlider.classList.toggle('checked', enabled);
});
};
/**
* Decorates the UI and registers event listener for the slider.
* @param {string} collectionId The collection id that this slider is associated
* with.
* @param {Object} dailyRefreshSlider The daily refresh slider.
*/
WallpaperManager.prototype.decorateDailyRefreshSlider = function(
collectionId, dailyRefreshSlider) {
if (!this.dailyRefreshSliderMap_)
this.dailyRefreshSliderMap_ = {};
this.dailyRefreshSliderMap_[collectionId] = dailyRefreshSlider;
this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
dailyRefreshSlider.addEventListener('click', () => {
var isSliderEnabled = dailyRefreshSlider.classList.contains('checked');
var isCollectionEnabled =
collectionId === this.dailyRefreshInfo_.collectionId;
if (isSliderEnabled !== isCollectionEnabled) {
console.error(
'There is a mismatch between the enabled daily refresh collection ' +
'and the slider state. This should never happen.');
return;
}
if (isSliderEnabled) {
// Disable daily refresh. The current value of the collection id and
// resume token can be discarded.
this.dailyRefreshInfo_ = {
enabled: false,
collectionId: null,
resumeToken: null
};
WallpaperUtil.saveDailyRefreshInfo(this.dailyRefreshInfo_);
this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
this.decorateCurrentWallpaperInfoBar_();
} else {
// Enable daily refresh but do not overwrite |dailyRefreshInfo_| yet
// (since it's still possible to revert). The resume token is left empty
// for now.
this.pendingDailyRefreshInfo_ = {
enabled: true,
collectionId: collectionId,
resumeToken: null
};
this.setDailyRefreshWallpaper_();
}
});
};
/**
* Fetches the image for daily refresh based on |pendingDailyRefreshInfo_|.
* Either sets it directly or enters preview mode.
* @private
*/
WallpaperManager.prototype.setDailyRefreshWallpaper_ = function() {
if (!this.pendingDailyRefreshInfo_)
return;
// There should be immediate UI update even though the info hasn't been saved.
this.updateDailyRefreshSliderStates_(this.pendingDailyRefreshInfo_);
if (this.isDuringPreview_())
$('spinner').hidden = false;
chrome.wallpaperPrivate.getSurpriseMeImage(
this.pendingDailyRefreshInfo_.collectionId,
this.pendingDailyRefreshInfo_.resumeToken,
(imageInfo, nextResumeToken) => {
var failureCallback = () => {
this.pendingDailyRefreshInfo_ = null;
// Restore the original states.
this.updateDailyRefreshSliderStates_(this.dailyRefreshInfo_);
$('spinner').hidden = true;
};
if (chrome.runtime.lastError) {
console.error(
'Error fetching daily refresh wallpaper for collection id: ' +
this.pendingDailyRefreshInfo_.collectionId);
failureCallback();
return;
}
this.pendingDailyRefreshInfo_.resumeToken = nextResumeToken;
// Find the name of the collection based on its id for display purpose.
var collectionName;
for (var i = 0; i < this.collectionsInfo_.length; ++i) {
if (this.collectionsInfo_[i]['collectionId'] ===
this.pendingDailyRefreshInfo_.collectionId) {
collectionName = this.collectionsInfo_[i]['collectionName'];
}
}
var dailyRefreshImageInfo = {
highResolutionURL:
imageInfo['imageUrl'] + str('highResolutionSuffix'),
layout: Constants.WallpaperThumbnailDefaultLayout,
source: Constants.WallpaperSourceEnum.Daily,
displayText: imageInfo['displayText'],
authorWebsite: imageInfo['actionUrl'],
collectionName: collectionName
};
var previewMode = this.shouldPreviewWallpaper_();
var successCallback = () => {
$('spinner').hidden = true;
var onWallpaperConfirmed = () => {
var date = new Date().toDateString();
WallpaperUtil.saveToLocalStorage(
Constants.AccessLastSurpriseWallpaperChangedDate, date, () => {
WallpaperUtil.enabledSyncThemesCallback(syncEnabled => {
var saveInfo = () => {
this.dailyRefreshInfo_ = this.pendingDailyRefreshInfo_;
WallpaperUtil.saveDailyRefreshInfo(
this.dailyRefreshInfo_);
this.onWallpaperChanged_(
dailyRefreshImageInfo,
dailyRefreshImageInfo.highResolutionURL);
this.pendingDailyRefreshInfo_ = null;
};
if (syncEnabled) {
WallpaperUtil.saveToSyncStorage(
Constants.AccessLastSurpriseWallpaperChangedDate,
date, saveInfo);
} else {
saveInfo();
}
});
});
};
if (previewMode) {
this.setWallpaperAttribution(dailyRefreshImageInfo);
this.onPreviewModeStarted_(
dailyRefreshImageInfo.source, onWallpaperConfirmed,
failureCallback, this.setDailyRefreshWallpaper_.bind(this));
} else {
onWallpaperConfirmed();
}
};
this.setSelectedOnlineWallpaper_(
dailyRefreshImageInfo, successCallback, failureCallback,
previewMode);
});
};
})(); })();
...@@ -181,6 +181,8 @@ found in the LICENSE file. ...@@ -181,6 +181,8 @@ found in the LICENSE file.
<div class="icon"></div> <div class="icon"></div>
<div class="text" i18n-content="centerCroppedLayout"></div> <div class="text" i18n-content="centerCroppedLayout"></div>
</div> </div>
<div id="refresh-wallpaper" class="daily-option"
i18n-content="refreshLabel"></div>
<div id="confirm-preview-wallpaper" class="preview-option" <div id="confirm-preview-wallpaper" class="preview-option"
i18n-content="confirmPreviewLabel"></div> i18n-content="confirmPreviewLabel"></div>
</div> </div>
......
...@@ -286,6 +286,10 @@ var chrome = { ...@@ -286,6 +286,10 @@ var chrome = {
}, },
getImagesInfo: function(collectionId, callback) { getImagesInfo: function(collectionId, callback) {
callback([{imageUrl: TestConstants.wallpaperUrl}]); callback([{imageUrl: TestConstants.wallpaperUrl}]);
},
getSurpriseMeImage: function(collectionId, resumeToken, callback) {
callback(
{imageUrl: TestConstants.wallpaperUrl}, null /*nextResumeToken=*/);
} }
}, },
runtime: {lastError: null}, runtime: {lastError: null},
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment