Commit 9b251c59 authored by John Lee's avatar John Lee Committed by Commit Bot

Navi: Allow users to preview NTP backgrounds

https://i.imgur.com/BAXJzRC.png

Bug: 924176
Change-Id: I4328752370dafa3c00d178b0b28a3320e26b071d
Reviewed-on: https://chromium-review.googlesource.com/c/1490053
Commit-Queue: John Lee <johntlee@chromium.org>
Reviewed-by: default avatarHector Carmona <hcarmona@chromium.org>
Cr-Commit-Position: refs/heads/master@{#636627}
parent f3c31fc7
...@@ -18,6 +18,12 @@ cr.define('nux', function() { ...@@ -18,6 +18,12 @@ cr.define('nux', function() {
/** @return {!Promise<!Array<!nux.NtpBackgroundData>>} */ /** @return {!Promise<!Array<!nux.NtpBackgroundData>>} */
getBackgrounds() {} getBackgrounds() {}
/**
* @param {string} url
* @return {!Promise<void>}
*/
preloadImage(url) {}
/** @param {number} id */ /** @param {number} id */
setBackground(id) {} setBackground(id) {}
} }
...@@ -29,6 +35,16 @@ cr.define('nux', function() { ...@@ -29,6 +35,16 @@ cr.define('nux', function() {
return cr.sendWithPromise('getBackgrounds'); return cr.sendWithPromise('getBackgrounds');
} }
/** @override */
preloadImage(url) {
return new Promise((resolve, reject) => {
const preloadedImage = new Image();
preloadedImage.onerror = reject;
preloadedImage.onload = resolve;
preloadedImage.src = url;
});
}
/** @override */ /** @override */
setBackground(id) { setBackground(id) {
chrome.send('setBackground', [id]); chrome.send('setBackground', [id]);
......
...@@ -20,6 +20,41 @@ ...@@ -20,6 +20,41 @@
text-align: center; text-align: center;
} }
#backgroundPreview {
background-position: center center;
background-repeat: no-repeat;
background-size: cover;
bottom: 0;
left: 0;
opacity: 0;
position: fixed;
right: 0;
top: 0;
transition: background 300ms, opacity 400ms;
}
#backgroundPreview.active {
opacity: 1;
}
#backgroundPreview::before {
/* Copied from browser/resources/local_ntp/custom_backgrounds.js */
background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3));
/* Pseudo element needs some content (even an empty string) to be
* displayed. */
content: '';
display: block;
height: 100%;
width: 100%;
}
.content {
/* Put a non-static position on the content so that it can have a
* higher stacking level than its previous sibling,
* the #backgroundPreview element. */
position: relative;
}
.ntp-background-logo { .ntp-background-logo {
content: -webkit-image-set( content: -webkit-image-set(
url(chrome://welcome/images/ntp_background_1x.png) 1x, url(chrome://welcome/images/ntp_background_1x.png) 1x,
...@@ -37,6 +72,11 @@ ...@@ -37,6 +72,11 @@
margin: 0; margin: 0;
margin-bottom: 46px; margin-bottom: 46px;
outline: none; outline: none;
transition: color 400ms;
}
#backgroundPreview.active + .content h1 {
color: white;
} }
.ntp-backgrounds-grid { .ntp-backgrounds-grid {
...@@ -116,6 +156,11 @@ ...@@ -116,6 +156,11 @@
margin-top: 56px; margin-top: 56px;
} }
.skip-button-container {
background: white;
border-radius: 4px;
}
iron-icon[icon='cr:chevron-right'] { iron-icon[icon='cr:chevron-right'] {
height: 20px; height: 20px;
margin-inline-end: -10px; margin-inline-end: -10px;
...@@ -127,35 +172,47 @@ ...@@ -127,35 +172,47 @@
transform: scaleX(-1); transform: scaleX(-1);
} }
</style> </style>
<div class="ntp-background-logo"></div> <div
<h1 tabindex="-1">$i18n{ntpBackgroundDescription}</h1> id="backgroundPreview"
on-transitionend="onBackgroundPreviewTransitionEnd_">
<div class="ntp-backgrounds-grid">
<template is="dom-repeat" items="[[backgrounds_]]">
<button
active$="[[isSelectedBackground_(item, selectedBackground_)]]"
aria-pressed$="[[getAriaPressedValue_(item, selectedBackground_)]]"
class="ntp-background-grid-button"
on-click="onBackgroundClick_"
on-keyup="onBackgroundKeyUp_"
on-pointerdown="onBackgroundPointerDown_">
<div class$="ntp-background-thumbnail [[item.thumbnailClass]]"></div>
<div class="ntp-background-title">[[item.title]]</div>
</button>
</template>
</div> </div>
<div class="button-bar"> <div class="content">
<paper-button on-click="onSkipClicked_"> <div class="ntp-background-logo"></div>
$i18n{skip} <h1 tabindex="-1">$i18n{ntpBackgroundDescription}</h1>
</paper-button>
<step-indicator model="[[indicatorModel]]"></step-indicator> <div class="ntp-backgrounds-grid">
<paper-button class="action-button" <template is="dom-repeat" items="[[backgrounds_]]">
disabled$="[[!hasValidSelectedBackground_(selectedBackground_)]]" <button
on-click="onNextClicked_"> active$="[[isSelectedBackground_(item, selectedBackground_)]]"
$i18n{next} aria-pressed$="[[getAriaPressedValue_(item,
<iron-icon icon="cr:chevron-right"></iron-icon> selectedBackground_)]]"
</paper-button> class="ntp-background-grid-button"
on-click="onBackgroundClick_"
on-keyup="onBackgroundKeyUp_"
on-pointerdown="onBackgroundPointerDown_">
<div
class$="ntp-background-thumbnail [[item.thumbnailClass]]">
</div>
<div class="ntp-background-title">[[item.title]]</div>
</button>
</template>
</div>
<div class="button-bar">
<div class="skip-button-container">
<paper-button on-click="onSkipClicked_">
$i18n{skip}
</paper-button>
</div>
<step-indicator model="[[indicatorModel]]"></step-indicator>
<paper-button class="action-button"
disabled$="[[!hasValidSelectedBackground_(selectedBackground_)]]"
on-click="onNextClicked_">
$i18n{next}
<iron-icon icon="cr:chevron-right"></iron-icon>
</paper-button>
</div>
</div> </div>
</template> </template>
......
...@@ -17,7 +17,10 @@ Polymer({ ...@@ -17,7 +17,10 @@ Polymer({
indicatorModel: Object, indicatorModel: Object,
/** @private {?nux.NtpBackgroundData} */ /** @private {?nux.NtpBackgroundData} */
selectedBackground_: Object, selectedBackground_: {
observer: 'onSelectedBackgroundChange_',
type: Object,
},
}, },
/** @private {?Array<!nux.NtpBackgroundData>} */ /** @private {?Array<!nux.NtpBackgroundData>} */
...@@ -38,13 +41,17 @@ Polymer({ ...@@ -38,13 +41,17 @@ Polymer({
thumbnailClass: '', thumbnailClass: '',
title: this.i18n('ntpBackgroundDefault'), title: this.i18n('ntpBackgroundDefault'),
}; };
this.selectedBackground_ = defaultBackground; if (!this.selectedBackground_) {
this.ntpBackgroundProxy_.getBackgrounds().then((backgrounds) => { this.selectedBackground_ = defaultBackground;
this.backgrounds_ = [ }
defaultBackground, if (!this.backgrounds_) {
...backgrounds, this.ntpBackgroundProxy_.getBackgrounds().then((backgrounds) => {
]; this.backgrounds_ = [
}); defaultBackground,
...backgrounds,
];
});
}
}, },
/** /**
...@@ -71,6 +78,33 @@ Polymer({ ...@@ -71,6 +78,33 @@ Polymer({
return background == this.selectedBackground_; return background == this.selectedBackground_;
}, },
/** @private */
onSelectedBackgroundChange_: function() {
const id = this.selectedBackground_.id;
if (id > -1) {
const imageUrl = this.selectedBackground_.imageUrl;
this.ntpBackgroundProxy_.preloadImage(imageUrl).then(() => {
if (this.selectedBackground_.id === id) {
this.$.backgroundPreview.classList.add('active');
this.$.backgroundPreview.style.backgroundImage = `url(${imageUrl})`;
}
});
} else {
this.$.backgroundPreview.classList.remove('active');
}
},
/** @private */
onBackgroundPreviewTransitionEnd_: function() {
// Whenever the #backgroundPreview transitions to a non-active, hidden
// state, remove the background image. This way, when the element
// transitions back to active, the previous background is not displayed.
if (!this.$.backgroundPreview.classList.contains('active')) {
this.$.backgroundPreview.style.backgroundImage = '';
}
},
/** /**
* @param {!{model: !{item: !nux.NtpBackgroundData}}} e * @param {!{model: !{item: !nux.NtpBackgroundData}}} e
* @private * @private
......
...@@ -54,6 +54,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -54,6 +54,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
base::ListValue list_value; base::ListValue list_value;
std::array<GURL, kOnboardingNtpBackgroundsCount> onboardingNtpBackgrounds = std::array<GURL, kOnboardingNtpBackgroundsCount> onboardingNtpBackgrounds =
GetOnboardingNtpBackgrounds(); GetOnboardingNtpBackgrounds();
const std::string kUrlPrefix = "preview-background.jpg?";
auto element = std::make_unique<base::DictionaryValue>(); auto element = std::make_unique<base::DictionaryValue>();
int id = static_cast<int>(NtpBackgrounds::kEarth); int id = static_cast<int>(NtpBackgrounds::kEarth);
...@@ -61,7 +62,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -61,7 +62,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
element->SetString("title", element->SetString("title",
l10n_util::GetStringUTF8( l10n_util::GetStringUTF8(
IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_EARTH_TITLE)); IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_EARTH_TITLE));
element->SetString("imageUrl", onboardingNtpBackgrounds[id].spec()); element->SetString("imageUrl", kUrlPrefix + std::to_string(id));
element->SetString("thumbnailClass", "earth"); element->SetString("thumbnailClass", "earth");
list_value.Append(std::move(element)); list_value.Append(std::move(element));
...@@ -71,7 +72,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -71,7 +72,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
element->SetString( element->SetString(
"title", l10n_util::GetStringUTF8( "title", l10n_util::GetStringUTF8(
IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_CITYSCAPE_TITLE)); IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_CITYSCAPE_TITLE));
element->SetString("imageUrl", onboardingNtpBackgrounds[id].spec()); element->SetString("imageUrl", kUrlPrefix + std::to_string(id));
element->SetString("thumbnailClass", "cityscape"); element->SetString("thumbnailClass", "cityscape");
list_value.Append(std::move(element)); list_value.Append(std::move(element));
...@@ -81,7 +82,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -81,7 +82,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
element->SetString( element->SetString(
"title", l10n_util::GetStringUTF8( "title", l10n_util::GetStringUTF8(
IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_LANDSCAPE_TITLE)); IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_LANDSCAPE_TITLE));
element->SetString("imageUrl", onboardingNtpBackgrounds[id].spec()); element->SetString("imageUrl", kUrlPrefix + std::to_string(id));
element->SetString("thumbnailClass", "landscape"); element->SetString("thumbnailClass", "landscape");
list_value.Append(std::move(element)); list_value.Append(std::move(element));
...@@ -91,7 +92,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -91,7 +92,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
element->SetString("title", element->SetString("title",
l10n_util::GetStringUTF8( l10n_util::GetStringUTF8(
IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_ART_TITLE)); IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_ART_TITLE));
element->SetString("imageUrl", onboardingNtpBackgrounds[id].spec()); element->SetString("imageUrl", kUrlPrefix + std::to_string(id));
element->SetString("thumbnailClass", "art"); element->SetString("thumbnailClass", "art");
list_value.Append(std::move(element)); list_value.Append(std::move(element));
...@@ -102,7 +103,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) { ...@@ -102,7 +103,7 @@ void NtpBackgroundHandler::HandleGetBackgrounds(const base::ListValue* args) {
"title", "title",
l10n_util::GetStringUTF8( l10n_util::GetStringUTF8(
IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_GEOMETRIC_SHAPES_TITLE)); IDS_ONBOARDING_WELCOME_NTP_BACKGROUND_GEOMETRIC_SHAPES_TITLE));
element->SetString("imageUrl", onboardingNtpBackgrounds[id].spec()); element->SetString("imageUrl", kUrlPrefix + std::to_string(id));
element->SetString("thumbnailClass", "geometric-shapes"); element->SetString("thumbnailClass", "geometric-shapes");
list_value.Append(std::move(element)); list_value.Append(std::move(element));
......
...@@ -8,15 +8,17 @@ cr.define('onboarding_ntp_background_test', function() { ...@@ -8,15 +8,17 @@ cr.define('onboarding_ntp_background_test', function() {
let backgrounds = [ let backgrounds = [
{ {
id: 0, id: 0,
title: 'Cat', title: 'Art',
imageUrl: 'some/cute/photo/of/a/cat', /* Image URLs are set to actual static images to prevent requesting
thumbnailClass: 'cat', * an external image. */
imageUrl: '../images/ntp_thumbnails/art.jpg',
thumbnailClass: 'art',
}, },
{ {
id: 1, id: 1,
title: 'Venice', title: 'Cityscape',
imageUrl: 'some/scenic/photo/of/a/beach', imageUrl: '../images/ntp_thumbnails/cityscape.jpg',
thumbnailClass: 'venice', thumbnailClass: 'cityscape',
}, },
]; ];
...@@ -66,6 +68,29 @@ cr.define('onboarding_ntp_background_test', function() { ...@@ -66,6 +68,29 @@ cr.define('onboarding_ntp_background_test', function() {
} }
}); });
test('test previewing a background and going back to default', function() {
const options = testElement.shadowRoot.querySelectorAll(
'.ntp-background-grid-button');
options[1].click();
return testNtpBackgroundProxy.whenCalled('preloadImage').then(() => {
assertEquals(
testElement.$.backgroundPreview.style.backgroundImage,
`url("${backgrounds[0].imageUrl}")`);
assertTrue(
testElement.$.backgroundPreview.classList.contains('active'));
// go back to the default option, and pretend all CSS transitions
// have completed
options[0].click();
testElement.$.backgroundPreview.dispatchEvent(
new Event('transitionend'));
assertEquals(testElement.$.backgroundPreview.style.backgroundImage, '');
assertFalse(
testElement.$.backgroundPreview.classList.contains('active'));
});
});
test('test disabling and enabling of the next button', function() { test('test disabling and enabling of the next button', function() {
const nextButton = testElement.shadowRoot.querySelector('.action-button'); const nextButton = testElement.shadowRoot.querySelector('.action-button');
assertTrue(nextButton.disabled); assertTrue(nextButton.disabled);
......
...@@ -7,6 +7,7 @@ class TestNtpBackgroundProxy extends TestBrowserProxy { ...@@ -7,6 +7,7 @@ class TestNtpBackgroundProxy extends TestBrowserProxy {
constructor() { constructor() {
super([ super([
'getBackgrounds', 'getBackgrounds',
'preloadImage',
'setBackground', 'setBackground',
]); ]);
...@@ -20,6 +21,12 @@ class TestNtpBackgroundProxy extends TestBrowserProxy { ...@@ -20,6 +21,12 @@ class TestNtpBackgroundProxy extends TestBrowserProxy {
return Promise.resolve(this.backgroundsList_); return Promise.resolve(this.backgroundsList_);
} }
/** @override */
preloadImage(url) {
this.methodCalled('preloadImage');
return Promise.resolve();
}
/** @override */ /** @override */
setBackground(id) { setBackground(id) {
this.methodCalled('setBackground', id); this.methodCalled('setBackground', id);
......
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