mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1881588 - Add Wallpaper component r=home-newtab-reviewers,fluent-reviewers,bolsson,thecount,maxxcrawford
Differential Revision: https://phabricator.services.mozilla.com/D205373
This commit is contained in:
parent
76ccf69421
commit
d57c2801d9
@ -1692,6 +1692,9 @@ pref("browser.partnerlink.campaign.topsites", "amzn_2020_a1");
|
||||
// Activates preloading of the new tab url.
|
||||
pref("browser.newtab.preload", true);
|
||||
|
||||
// Preference to enable wallpaper selection in the Customize Menu of new tab page
|
||||
pref("browser.newtabpage.activity-stream.newtabWallpapers.enabled", false);
|
||||
|
||||
// Current new tab page background image.
|
||||
pref("browser.newtabpage.activity-stream.newtabWallpapers.wallpaper", "");
|
||||
|
||||
|
@ -160,6 +160,7 @@ for (const type of [
|
||||
"UPDATE_PINNED_SEARCH_SHORTCUTS",
|
||||
"UPDATE_SEARCH_SHORTCUTS",
|
||||
"UPDATE_SECTION_PREFS",
|
||||
"WALLPAPERS_SET",
|
||||
"WEBEXT_CLICK",
|
||||
"WEBEXT_DISMISS",
|
||||
]) {
|
||||
|
@ -101,6 +101,9 @@ export const INITIAL_STATE = {
|
||||
// Hide the search box after handing off to AwesomeBar and user starts typing.
|
||||
hide: false,
|
||||
},
|
||||
Wallpapers: {
|
||||
wallpaperList: [],
|
||||
},
|
||||
};
|
||||
|
||||
function App(prevState = INITIAL_STATE.App, action) {
|
||||
@ -841,6 +844,15 @@ function Search(prevState = INITIAL_STATE.Search, action) {
|
||||
}
|
||||
}
|
||||
|
||||
function Wallpapers(prevState = INITIAL_STATE.Wallpapers, action) {
|
||||
switch (action.type) {
|
||||
case at.WALLPAPERS_SET:
|
||||
return { wallpaperList: action.data };
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
}
|
||||
|
||||
export const reducers = {
|
||||
TopSites,
|
||||
App,
|
||||
@ -852,4 +864,5 @@ export const reducers = {
|
||||
Personalization,
|
||||
DiscoveryStream,
|
||||
Search,
|
||||
Wallpapers,
|
||||
};
|
||||
|
@ -110,6 +110,7 @@ export class BaseContent extends React.PureComponent {
|
||||
this.handleOnKeyDown = this.handleOnKeyDown.bind(this);
|
||||
this.onWindowScroll = debounce(this.onWindowScroll.bind(this), 5);
|
||||
this.setPref = this.setPref.bind(this);
|
||||
this.updateWallpaper = this.updateWallpaper.bind(this);
|
||||
this.state = { fixedSearch: false, firstVisibleTimestamp: null };
|
||||
}
|
||||
|
||||
@ -192,11 +193,64 @@ export class BaseContent extends React.PureComponent {
|
||||
this.props.dispatch(ac.SetPref(pref, value));
|
||||
}
|
||||
|
||||
renderWallpaperAttribution() {
|
||||
const activeWallpaper =
|
||||
this.props.Prefs.values["newtabWallpapers.wallpaper"];
|
||||
const { wallpaperList } = this.props.Wallpapers;
|
||||
const selected = wallpaperList.find(wp => wp.title === activeWallpaper);
|
||||
// make sure a wallpaper is selected and that the attribution also exists
|
||||
if (!selected?.attribution) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { name, webpage } = selected.attribution;
|
||||
if (activeWallpaper && wallpaperList && name.url) {
|
||||
return (
|
||||
<p
|
||||
className={`wallpaper-attribution`}
|
||||
key={name}
|
||||
data-l10n-id="newtab-wallpaper-attribution"
|
||||
data-l10n-args={JSON.stringify({
|
||||
author_string: name.string,
|
||||
author_url: name.url,
|
||||
webpage_string: webpage.string,
|
||||
webpage_url: webpage.url,
|
||||
})}
|
||||
>
|
||||
<a data-l10n-name="name-link" href={name.url}>
|
||||
{name.string}
|
||||
</a>
|
||||
<a data-l10n-name="webpage-link" href={webpage.url}>
|
||||
{webpage.string}
|
||||
</a>
|
||||
</p>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async updateWallpaper() {
|
||||
const prefs = this.props.Prefs.values;
|
||||
const activeWallpaper = prefs["newtabWallpapers.wallpaper"];
|
||||
const { wallpaperList } = this.props.Wallpapers;
|
||||
if (wallpaperList) {
|
||||
const wallpaper =
|
||||
wallpaperList.find(wp => wp.title === activeWallpaper) || "";
|
||||
global.document?.body.style.setProperty(
|
||||
"--newtab-wallpaper",
|
||||
`url(${wallpaper?.wallpaperUrl || ""})`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { props } = this;
|
||||
const { App } = props;
|
||||
const { initialized, customizeMenuVisible } = App;
|
||||
const prefs = props.Prefs.values;
|
||||
const activeWallpaper = prefs["newtabWallpapers.wallpaper"];
|
||||
const wallpapersEnabled = prefs["newtabWallpapers.enabled"];
|
||||
|
||||
const { pocketConfig } = prefs;
|
||||
|
||||
const isDiscoveryStream =
|
||||
@ -247,6 +301,9 @@ export class BaseContent extends React.PureComponent {
|
||||
]
|
||||
.filter(v => v)
|
||||
.join(" ");
|
||||
if (wallpapersEnabled) {
|
||||
this.updateWallpaper();
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
@ -256,6 +313,8 @@ export class BaseContent extends React.PureComponent {
|
||||
openPreferences={this.openPreferences}
|
||||
setPref={this.setPref}
|
||||
enabledSections={enabledSections}
|
||||
wallpapersEnabled={wallpapersEnabled}
|
||||
activeWallpaper={activeWallpaper}
|
||||
pocketRegion={pocketRegion}
|
||||
mayHaveSponsoredTopSites={mayHaveSponsoredTopSites}
|
||||
mayHaveSponsoredStories={mayHaveSponsoredStories}
|
||||
@ -292,6 +351,7 @@ export class BaseContent extends React.PureComponent {
|
||||
)}
|
||||
</div>
|
||||
<ConfirmDialog />
|
||||
{wallpapersEnabled && this.renderWallpaperAttribution()}
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
@ -309,4 +369,5 @@ export const Base = connect(state => ({
|
||||
Sections: state.Sections,
|
||||
DiscoveryStream: state.DiscoveryStream,
|
||||
Search: state.Search,
|
||||
Wallpapers: state.Wallpapers,
|
||||
}))(_Base);
|
||||
|
@ -24,10 +24,17 @@
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: $wrapper-default-width;
|
||||
padding: 0;
|
||||
|
||||
.vertical-center-wrapper {
|
||||
margin: auto 0;
|
||||
}
|
||||
|
||||
section {
|
||||
margin-bottom: $section-spacing;
|
||||
position: relative;
|
||||
@ -124,3 +131,32 @@ main {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wallpaper-attribution {
|
||||
padding: 0 $section-horizontal-padding;
|
||||
font-size: 14px;
|
||||
|
||||
&.theme-light {
|
||||
display: inline-block;
|
||||
|
||||
@include dark-theme-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.theme-dark {
|
||||
display: none;
|
||||
|
||||
@include dark-theme-only {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: var(--newtab-element-color);
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
import React from "react";
|
||||
import { actionCreators as ac } from "common/Actions.mjs";
|
||||
import { SafeAnchor } from "../../DiscoveryStreamComponents/SafeAnchor/SafeAnchor";
|
||||
import { WallpapersSection } from "../../WallpapersSection/WallpapersSection";
|
||||
|
||||
export class ContentSection extends React.PureComponent {
|
||||
constructor(props) {
|
||||
@ -98,6 +99,9 @@ export class ContentSection extends React.PureComponent {
|
||||
mayHaveRecentSaves,
|
||||
openPreferences,
|
||||
spocMessageVariant,
|
||||
wallpapersEnabled,
|
||||
activeWallpaper,
|
||||
setPref,
|
||||
} = this.props;
|
||||
const {
|
||||
topSitesEnabled,
|
||||
@ -111,6 +115,15 @@ export class ContentSection extends React.PureComponent {
|
||||
|
||||
return (
|
||||
<div className="home-section">
|
||||
{wallpapersEnabled && (
|
||||
<div className="wallpapers-section">
|
||||
<h2 data-l10n-id="newtab-wallpaper-title"></h2>
|
||||
<WallpapersSection
|
||||
setPref={setPref}
|
||||
activeWallpaper={activeWallpaper}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div id="shortcuts-section" className="section">
|
||||
<moz-toggle
|
||||
id="shortcuts-toggle"
|
||||
|
@ -2,7 +2,6 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import { BackgroundsSection } from "content-src/components/CustomizeMenu/BackgroundsSection/BackgroundsSection";
|
||||
import { ContentSection } from "content-src/components/CustomizeMenu/ContentSection/ContentSection";
|
||||
import { connect } from "react-redux";
|
||||
import React from "react";
|
||||
@ -62,11 +61,12 @@ export class _CustomizeMenu extends React.PureComponent {
|
||||
data-l10n-id="newtab-custom-close-button"
|
||||
ref={c => (this.closeButton = c)}
|
||||
/>
|
||||
<BackgroundsSection />
|
||||
<ContentSection
|
||||
openPreferences={this.props.openPreferences}
|
||||
setPref={this.props.setPref}
|
||||
enabledSections={this.props.enabledSections}
|
||||
wallpapersEnabled={this.props.wallpapersEnabled}
|
||||
activeWallpaper={this.props.activeWallpaper}
|
||||
pocketRegion={this.props.pocketRegion}
|
||||
mayHaveSponsoredTopSites={this.props.mayHaveSponsoredTopSites}
|
||||
mayHaveSponsoredStories={this.props.mayHaveSponsoredStories}
|
||||
|
@ -119,6 +119,10 @@
|
||||
grid-row-gap: 32px;
|
||||
padding: 0 16px;
|
||||
|
||||
.wallpapers-section h2 {
|
||||
font-size: inherit;
|
||||
}
|
||||
|
||||
.section {
|
||||
moz-toggle {
|
||||
margin-bottom: 10px;
|
||||
|
@ -0,0 +1,93 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
import React from "react";
|
||||
import { connect } from "react-redux";
|
||||
|
||||
export class _WallpapersSection extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleReset = this.handleReset.bind(this);
|
||||
this.prefersHighContrastQuery = null;
|
||||
this.prefersDarkQuery = null;
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.prefersHighContrastQuery = globalThis.matchMedia(
|
||||
"(forced-colors: active)"
|
||||
);
|
||||
this.prefersDarkQuery = globalThis.matchMedia(
|
||||
"(prefers-color-scheme: dark)"
|
||||
);
|
||||
[this.prefersHighContrastQuery, this.prefersDarkQuery].forEach(
|
||||
colorTheme => {
|
||||
colorTheme.addEventListener("change", this.handleReset);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
[this.prefersHighContrastQuery, this.prefersDarkQuery].forEach(
|
||||
colorTheme => {
|
||||
colorTheme.removeEventListener("change", this.handleReset);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
handleChange(event) {
|
||||
const { id } = event.target;
|
||||
this.props.setPref("newtabWallpapers.wallpaper", id);
|
||||
}
|
||||
|
||||
handleReset() {
|
||||
this.props.setPref("newtabWallpapers.wallpaper", "i");
|
||||
}
|
||||
|
||||
render() {
|
||||
const { wallpaperList } = this.props.Wallpapers;
|
||||
const { activeWallpaper } = this.props;
|
||||
return (
|
||||
<div>
|
||||
<fieldset className="wallpaper-list">
|
||||
{wallpaperList.map(({ title, theme, fluent_id }) => {
|
||||
return (
|
||||
<>
|
||||
<input
|
||||
onChange={this.handleChange}
|
||||
type="radio"
|
||||
name="wallpaper"
|
||||
id={title}
|
||||
value={title}
|
||||
checked={title === activeWallpaper}
|
||||
aria-checked={title === activeWallpaper}
|
||||
className={`wallpaper-input theme-${theme} ${title}`}
|
||||
/>
|
||||
<label
|
||||
htmlFor={title}
|
||||
className="sr-only"
|
||||
data-l10n-id={fluent_id}
|
||||
>
|
||||
{fluent_id}
|
||||
</label>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</fieldset>
|
||||
<button
|
||||
className="wallpapers-reset"
|
||||
onClick={this.handleReset}
|
||||
data-l10n-id="newtab-wallpaper-reset"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export const WallpapersSection = connect(state => {
|
||||
return {
|
||||
Wallpapers: state.Wallpapers,
|
||||
Prefs: state.Prefs,
|
||||
};
|
||||
})(_WallpapersSection);
|
@ -0,0 +1,82 @@
|
||||
.wallpaper-list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: 86px;
|
||||
margin: 16px 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
|
||||
.wallpaper-input,
|
||||
.sr-only {
|
||||
&.theme-light {
|
||||
display: inline-block;
|
||||
|
||||
@include dark-theme-only {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.theme-dark {
|
||||
display: none;
|
||||
|
||||
@include dark-theme-only {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wallpaper-input {
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 86px;
|
||||
width: 100%;
|
||||
box-shadow: $shadow-secondary;
|
||||
border-radius: 8px;
|
||||
background-clip: content-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
outline: 2px solid transparent;
|
||||
|
||||
$wallpapers: dark-aurora, dark-city, dark-color, dark-mountain, dark-panda, dark-sky, light-beach, light-color, light-landscape, light-mountain, light-redpanda, light-sky;
|
||||
|
||||
@each $wallpaper in $wallpapers {
|
||||
&.#{$wallpaper} {
|
||||
background-image: url('chrome://activity-stream/content/data/content/assets/wallpapers/#{$wallpaper}.avif')
|
||||
}
|
||||
}
|
||||
|
||||
&:checked {
|
||||
outline-color: var(--newtab-primary-action-background);
|
||||
}
|
||||
|
||||
&:hover {
|
||||
filter: brightness(55%);
|
||||
outline-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
// visually hide label, but still read by screen readers
|
||||
.sr-only {
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
|
||||
.wallpapers-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
margin-inline: auto;
|
||||
display: block;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--newtab-text-primary-color);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
@ -21,6 +21,12 @@ body {
|
||||
background-color: var(--newtab-background-color);
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif;
|
||||
font-size: 16px;
|
||||
// rules for HNT wallpapers
|
||||
background-image: var(--newtab-wallpaper, '');
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
@ -137,6 +143,7 @@ input {
|
||||
@import '../components/ContextMenu/ContextMenu';
|
||||
@import '../components/ConfirmDialog/ConfirmDialog';
|
||||
@import '../components/CustomizeMenu/CustomizeMenu';
|
||||
@import '../components/WallpapersSection/WallpapersSection';
|
||||
@import '../components/Card/Card';
|
||||
@import '../components/CollapsibleSection/CollapsibleSection';
|
||||
@import '../components/DiscoveryStreamAdmin/DiscoveryStreamAdmin';
|
||||
|
@ -276,6 +276,11 @@ body {
|
||||
background-color: var(--newtab-background-color);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
background-image: var(--newtab-wallpaper, "");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
@ -405,10 +410,16 @@ input[type=text], input[type=search] {
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 274px;
|
||||
padding: 0;
|
||||
}
|
||||
main .vertical-center-wrapper {
|
||||
margin: auto 0;
|
||||
}
|
||||
main section {
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
@ -489,6 +500,29 @@ main section {
|
||||
background-color: var(--newtab-element-active-color);
|
||||
}
|
||||
|
||||
.wallpaper-attribution {
|
||||
padding: 0 25px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.wallpaper-attribution.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-attribution.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-attribution a {
|
||||
color: var(--newtab-element-color);
|
||||
}
|
||||
.wallpaper-attribution a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.as-error-fallback {
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
@ -1694,6 +1728,9 @@ main section {
|
||||
grid-row-gap: 32px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
.home-section .wallpapers-section h2 {
|
||||
font-size: inherit;
|
||||
}
|
||||
.home-section .section moz-toggle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -1830,6 +1867,108 @@ main section {
|
||||
box-shadow: 0 0 0 2px var(--newtab-primary-action-background-dimmed);
|
||||
}
|
||||
|
||||
.wallpaper-list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: 86px;
|
||||
margin: 16px 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-light,
|
||||
.wallpaper-list .sr-only.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-light,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-dark,
|
||||
.wallpaper-list .sr-only.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-dark,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input {
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 86px;
|
||||
width: 100%;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2);
|
||||
border-radius: 8px;
|
||||
background-clip: content-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-aurora {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-aurora.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-city {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-city.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-panda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-panda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-beach {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-beach.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-landscape {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-landscape.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-redpanda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-redpanda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:checked {
|
||||
outline-color: var(--newtab-primary-action-background);
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:hover {
|
||||
filter: brightness(55%);
|
||||
outline-color: transparent;
|
||||
}
|
||||
.wallpaper-list .sr-only {
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.wallpapers-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
margin-inline: auto;
|
||||
display: block;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--newtab-text-primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.wallpapers-reset:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
@ -280,6 +280,11 @@ body {
|
||||
background-color: var(--newtab-background-color);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
background-image: var(--newtab-wallpaper, "");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
@ -409,10 +414,16 @@ input[type=text], input[type=search] {
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 274px;
|
||||
padding: 0;
|
||||
}
|
||||
main .vertical-center-wrapper {
|
||||
margin: auto 0;
|
||||
}
|
||||
main section {
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
@ -493,6 +504,29 @@ main section {
|
||||
background-color: var(--newtab-element-active-color);
|
||||
}
|
||||
|
||||
.wallpaper-attribution {
|
||||
padding: 0 25px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.wallpaper-attribution.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-attribution.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-attribution a {
|
||||
color: var(--newtab-element-color);
|
||||
}
|
||||
.wallpaper-attribution a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.as-error-fallback {
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
@ -1698,6 +1732,9 @@ main section {
|
||||
grid-row-gap: 32px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
.home-section .wallpapers-section h2 {
|
||||
font-size: inherit;
|
||||
}
|
||||
.home-section .section moz-toggle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -1834,6 +1871,108 @@ main section {
|
||||
box-shadow: 0 0 0 2px var(--newtab-primary-action-background-dimmed);
|
||||
}
|
||||
|
||||
.wallpaper-list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: 86px;
|
||||
margin: 16px 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-light,
|
||||
.wallpaper-list .sr-only.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-light,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-dark,
|
||||
.wallpaper-list .sr-only.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-dark,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input {
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 86px;
|
||||
width: 100%;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2);
|
||||
border-radius: 8px;
|
||||
background-clip: content-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-aurora {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-aurora.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-city {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-city.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-panda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-panda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-beach {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-beach.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-landscape {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-landscape.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-redpanda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-redpanda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:checked {
|
||||
outline-color: var(--newtab-primary-action-background);
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:hover {
|
||||
filter: brightness(55%);
|
||||
outline-color: transparent;
|
||||
}
|
||||
.wallpaper-list .sr-only {
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.wallpapers-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
margin-inline: auto;
|
||||
display: block;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--newtab-text-primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.wallpapers-reset:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
@ -276,6 +276,11 @@ body {
|
||||
background-color: var(--newtab-background-color);
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
|
||||
font-size: 16px;
|
||||
background-image: var(--newtab-wallpaper, "");
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.no-scroll {
|
||||
@ -405,10 +410,16 @@ input[type=text], input[type=search] {
|
||||
}
|
||||
|
||||
main {
|
||||
margin: auto;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
width: 274px;
|
||||
padding: 0;
|
||||
}
|
||||
main .vertical-center-wrapper {
|
||||
margin: auto 0;
|
||||
}
|
||||
main section {
|
||||
margin-bottom: 20px;
|
||||
position: relative;
|
||||
@ -489,6 +500,29 @@ main section {
|
||||
background-color: var(--newtab-element-active-color);
|
||||
}
|
||||
|
||||
.wallpaper-attribution {
|
||||
padding: 0 25px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.wallpaper-attribution.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-attribution.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-attribution.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-attribution a {
|
||||
color: var(--newtab-element-color);
|
||||
}
|
||||
.wallpaper-attribution a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.as-error-fallback {
|
||||
align-items: center;
|
||||
border-radius: 3px;
|
||||
@ -1694,6 +1728,9 @@ main section {
|
||||
grid-row-gap: 32px;
|
||||
padding: 0 16px;
|
||||
}
|
||||
.home-section .wallpapers-section h2 {
|
||||
font-size: inherit;
|
||||
}
|
||||
.home-section .section moz-toggle {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@ -1830,6 +1867,108 @@ main section {
|
||||
box-shadow: 0 0 0 2px var(--newtab-primary-action-background-dimmed);
|
||||
}
|
||||
|
||||
.wallpaper-list {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
grid-template-columns: 1fr 1fr 1fr;
|
||||
grid-auto-rows: 86px;
|
||||
margin: 16px 0;
|
||||
padding: 0;
|
||||
border: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-light,
|
||||
.wallpaper-list .sr-only.theme-light {
|
||||
display: inline-block;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-light,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-light {
|
||||
display: none;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.theme-dark,
|
||||
.wallpaper-list .sr-only.theme-dark {
|
||||
display: none;
|
||||
}
|
||||
[lwt-newtab-brighttext] .wallpaper-list .wallpaper-input.theme-dark,
|
||||
[lwt-newtab-brighttext] .wallpaper-list .sr-only.theme-dark {
|
||||
display: inline-block;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input {
|
||||
appearance: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
height: 86px;
|
||||
width: 100%;
|
||||
box-shadow: 0 1px 4px 0 rgba(12, 12, 13, 0.2);
|
||||
border-radius: 8px;
|
||||
background-clip: content-box;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
cursor: pointer;
|
||||
outline: 2px solid transparent;
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-aurora {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-aurora.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-city {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-city.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-panda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-panda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.dark-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/dark-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-beach {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-beach.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-color {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-color.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-landscape {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-landscape.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-mountain {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-mountain.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-redpanda {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-redpanda.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input.light-sky {
|
||||
background-image: url("chrome://activity-stream/content/data/content/assets/wallpapers/light-sky.avif");
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:checked {
|
||||
outline-color: var(--newtab-primary-action-background);
|
||||
}
|
||||
.wallpaper-list .wallpaper-input:hover {
|
||||
filter: brightness(55%);
|
||||
outline-color: transparent;
|
||||
}
|
||||
.wallpaper-list .sr-only {
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.wallpapers-reset {
|
||||
background: none;
|
||||
border: none;
|
||||
text-decoration: underline;
|
||||
margin-inline: auto;
|
||||
display: block;
|
||||
font-size: var(--font-size-small);
|
||||
color: var(--newtab-text-primary-color);
|
||||
cursor: pointer;
|
||||
}
|
||||
.wallpapers-reset:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* stylelint-disable max-nesting-depth */
|
||||
.card-outer {
|
||||
background: var(--newtab-background-color-secondary);
|
||||
|
@ -233,6 +233,7 @@ for (const type of [
|
||||
"UPDATE_PINNED_SEARCH_SHORTCUTS",
|
||||
"UPDATE_SEARCH_SHORTCUTS",
|
||||
"UPDATE_SECTION_PREFS",
|
||||
"WALLPAPERS_SET",
|
||||
"WEBEXT_CLICK",
|
||||
"WEBEXT_DISMISS",
|
||||
]) {
|
||||
@ -5530,6 +5531,9 @@ const INITIAL_STATE = {
|
||||
// Hide the search box after handing off to AwesomeBar and user starts typing.
|
||||
hide: false,
|
||||
},
|
||||
Wallpapers: {
|
||||
wallpaperList: [],
|
||||
},
|
||||
};
|
||||
|
||||
function App(prevState = INITIAL_STATE.App, action) {
|
||||
@ -6270,6 +6274,15 @@ function Search(prevState = INITIAL_STATE.Search, action) {
|
||||
}
|
||||
}
|
||||
|
||||
function Wallpapers(prevState = INITIAL_STATE.Wallpapers, action) {
|
||||
switch (action.type) {
|
||||
case actionTypes.WALLPAPERS_SET:
|
||||
return { wallpaperList: action.data };
|
||||
default:
|
||||
return prevState;
|
||||
}
|
||||
}
|
||||
|
||||
const reducers = {
|
||||
TopSites,
|
||||
App,
|
||||
@ -6281,6 +6294,7 @@ const reducers = {
|
||||
Personalization: Reducers_sys_Personalization,
|
||||
DiscoveryStream,
|
||||
Search,
|
||||
Wallpapers,
|
||||
};
|
||||
|
||||
;// CONCATENATED MODULE: ./content-src/components/TopSites/TopSiteFormInput.jsx
|
||||
@ -8833,17 +8847,83 @@ const DiscoveryStreamBase = (0,external_ReactRedux_namespaceObject.connect)(stat
|
||||
document: globalThis.document,
|
||||
App: state.App
|
||||
}))(_DiscoveryStreamBase);
|
||||
;// CONCATENATED MODULE: ./content-src/components/CustomizeMenu/BackgroundsSection/BackgroundsSection.jsx
|
||||
;// CONCATENATED MODULE: ./content-src/components/WallpapersSection/WallpapersSection.jsx
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
|
||||
class BackgroundsSection extends (external_React_default()).PureComponent {
|
||||
|
||||
class _WallpapersSection extends (external_React_default()).PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleChange = this.handleChange.bind(this);
|
||||
this.handleReset = this.handleReset.bind(this);
|
||||
this.prefersHighContrastQuery = null;
|
||||
this.prefersDarkQuery = null;
|
||||
}
|
||||
componentDidMount() {
|
||||
this.prefersHighContrastQuery = globalThis.matchMedia("(forced-colors: active)");
|
||||
this.prefersDarkQuery = globalThis.matchMedia("(prefers-color-scheme: dark)");
|
||||
[this.prefersHighContrastQuery, this.prefersDarkQuery].forEach(colorTheme => {
|
||||
colorTheme.addEventListener("change", this.handleReset);
|
||||
});
|
||||
}
|
||||
componentWillUnmount() {
|
||||
[this.prefersHighContrastQuery, this.prefersDarkQuery].forEach(colorTheme => {
|
||||
colorTheme.removeEventListener("change", this.handleReset);
|
||||
});
|
||||
}
|
||||
handleChange(event) {
|
||||
const {
|
||||
id
|
||||
} = event.target;
|
||||
this.props.setPref("newtabWallpapers.wallpaper", id);
|
||||
}
|
||||
handleReset() {
|
||||
this.props.setPref("newtabWallpapers.wallpaper", "i");
|
||||
}
|
||||
render() {
|
||||
return /*#__PURE__*/external_React_default().createElement("div", null);
|
||||
const {
|
||||
wallpaperList
|
||||
} = this.props.Wallpapers;
|
||||
const {
|
||||
activeWallpaper
|
||||
} = this.props;
|
||||
return /*#__PURE__*/external_React_default().createElement("div", null, /*#__PURE__*/external_React_default().createElement("fieldset", {
|
||||
className: "wallpaper-list"
|
||||
}, wallpaperList.map(({
|
||||
title,
|
||||
theme,
|
||||
fluent_id
|
||||
}) => {
|
||||
return /*#__PURE__*/external_React_default().createElement((external_React_default()).Fragment, null, /*#__PURE__*/external_React_default().createElement("input", {
|
||||
onChange: this.handleChange,
|
||||
type: "radio",
|
||||
name: "wallpaper",
|
||||
id: title,
|
||||
value: title,
|
||||
checked: title === activeWallpaper,
|
||||
"aria-checked": title === activeWallpaper,
|
||||
className: `wallpaper-input theme-${theme} ${title}`
|
||||
}), /*#__PURE__*/external_React_default().createElement("label", {
|
||||
htmlFor: title,
|
||||
className: "sr-only",
|
||||
"data-l10n-id": fluent_id
|
||||
}, fluent_id));
|
||||
})), /*#__PURE__*/external_React_default().createElement("button", {
|
||||
className: "wallpapers-reset",
|
||||
onClick: this.handleReset,
|
||||
"data-l10n-id": "newtab-wallpaper-reset"
|
||||
}));
|
||||
}
|
||||
}
|
||||
const WallpapersSection = (0,external_ReactRedux_namespaceObject.connect)(state => {
|
||||
return {
|
||||
Wallpapers: state.Wallpapers,
|
||||
Prefs: state.Prefs
|
||||
};
|
||||
})(_WallpapersSection);
|
||||
;// CONCATENATED MODULE: ./content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
@ -8852,6 +8932,7 @@ class BackgroundsSection extends (external_React_default()).PureComponent {
|
||||
|
||||
|
||||
|
||||
|
||||
class ContentSection extends (external_React_default()).PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -8930,7 +9011,10 @@ class ContentSection extends (external_React_default()).PureComponent {
|
||||
mayHaveSponsoredStories,
|
||||
mayHaveRecentSaves,
|
||||
openPreferences,
|
||||
spocMessageVariant
|
||||
spocMessageVariant,
|
||||
wallpapersEnabled,
|
||||
activeWallpaper,
|
||||
setPref
|
||||
} = this.props;
|
||||
const {
|
||||
topSitesEnabled,
|
||||
@ -8943,7 +9027,14 @@ class ContentSection extends (external_React_default()).PureComponent {
|
||||
} = enabledSections;
|
||||
return /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "home-section"
|
||||
}, /*#__PURE__*/external_React_default().createElement("div", {
|
||||
}, wallpapersEnabled && /*#__PURE__*/external_React_default().createElement("div", {
|
||||
className: "wallpapers-section"
|
||||
}, /*#__PURE__*/external_React_default().createElement("h2", {
|
||||
"data-l10n-id": "newtab-wallpaper-title"
|
||||
}), /*#__PURE__*/external_React_default().createElement(WallpapersSection, {
|
||||
setPref: setPref,
|
||||
activeWallpaper: activeWallpaper
|
||||
})), /*#__PURE__*/external_React_default().createElement("div", {
|
||||
id: "shortcuts-section",
|
||||
className: "section"
|
||||
}, /*#__PURE__*/external_React_default().createElement("moz-toggle", {
|
||||
@ -9091,7 +9182,6 @@ class ContentSection extends (external_React_default()).PureComponent {
|
||||
|
||||
|
||||
|
||||
|
||||
class _CustomizeMenu extends (external_React_default()).PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
@ -9135,10 +9225,12 @@ class _CustomizeMenu extends (external_React_default()).PureComponent {
|
||||
className: "close-button",
|
||||
"data-l10n-id": "newtab-custom-close-button",
|
||||
ref: c => this.closeButton = c
|
||||
}), /*#__PURE__*/external_React_default().createElement(BackgroundsSection, null), /*#__PURE__*/external_React_default().createElement(ContentSection, {
|
||||
}), /*#__PURE__*/external_React_default().createElement(ContentSection, {
|
||||
openPreferences: this.props.openPreferences,
|
||||
setPref: this.props.setPref,
|
||||
enabledSections: this.props.enabledSections,
|
||||
wallpapersEnabled: this.props.wallpapersEnabled,
|
||||
activeWallpaper: this.props.activeWallpaper,
|
||||
pocketRegion: this.props.pocketRegion,
|
||||
mayHaveSponsoredTopSites: this.props.mayHaveSponsoredTopSites,
|
||||
mayHaveSponsoredStories: this.props.mayHaveSponsoredStories,
|
||||
@ -9453,6 +9545,7 @@ class BaseContent extends (external_React_default()).PureComponent {
|
||||
this.handleOnKeyDown = this.handleOnKeyDown.bind(this);
|
||||
this.onWindowScroll = debounce(this.onWindowScroll.bind(this), 5);
|
||||
this.setPref = this.setPref.bind(this);
|
||||
this.updateWallpaper = this.updateWallpaper.bind(this);
|
||||
this.state = {
|
||||
fixedSearch: false,
|
||||
firstVisibleTimestamp: null
|
||||
@ -9535,6 +9628,52 @@ class BaseContent extends (external_React_default()).PureComponent {
|
||||
setPref(pref, value) {
|
||||
this.props.dispatch(actionCreators.SetPref(pref, value));
|
||||
}
|
||||
renderWallpaperAttribution() {
|
||||
const activeWallpaper = this.props.Prefs.values["newtabWallpapers.wallpaper"];
|
||||
const {
|
||||
wallpaperList
|
||||
} = this.props.Wallpapers;
|
||||
const selected = wallpaperList.find(wp => wp.title === activeWallpaper);
|
||||
// make sure a wallpaper is selected and that the attribution also exists
|
||||
if (!selected?.attribution) {
|
||||
return null;
|
||||
}
|
||||
const {
|
||||
name,
|
||||
webpage
|
||||
} = selected.attribution;
|
||||
if (activeWallpaper && wallpaperList && name.url) {
|
||||
return /*#__PURE__*/external_React_default().createElement("p", {
|
||||
className: `wallpaper-attribution`,
|
||||
key: name,
|
||||
"data-l10n-id": "newtab-wallpaper-attribution",
|
||||
"data-l10n-args": JSON.stringify({
|
||||
author_string: name.string,
|
||||
author_url: name.url,
|
||||
webpage_string: webpage.string,
|
||||
webpage_url: webpage.url
|
||||
})
|
||||
}, /*#__PURE__*/external_React_default().createElement("a", {
|
||||
"data-l10n-name": "name-link",
|
||||
href: name.url
|
||||
}, name.string), /*#__PURE__*/external_React_default().createElement("a", {
|
||||
"data-l10n-name": "webpage-link",
|
||||
href: webpage.url
|
||||
}, webpage.string));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async updateWallpaper() {
|
||||
const prefs = this.props.Prefs.values;
|
||||
const activeWallpaper = prefs["newtabWallpapers.wallpaper"];
|
||||
const {
|
||||
wallpaperList
|
||||
} = this.props.Wallpapers;
|
||||
if (wallpaperList) {
|
||||
const wallpaper = wallpaperList.find(wp => wp.title === activeWallpaper) || "";
|
||||
__webpack_require__.g.document?.body.style.setProperty("--newtab-wallpaper", `url(${wallpaper?.wallpaperUrl || ""})`);
|
||||
}
|
||||
}
|
||||
render() {
|
||||
const {
|
||||
props
|
||||
@ -9547,6 +9686,8 @@ class BaseContent extends (external_React_default()).PureComponent {
|
||||
customizeMenuVisible
|
||||
} = App;
|
||||
const prefs = props.Prefs.values;
|
||||
const activeWallpaper = prefs["newtabWallpapers.wallpaper"];
|
||||
const wallpapersEnabled = prefs["newtabWallpapers.enabled"];
|
||||
const {
|
||||
pocketConfig
|
||||
} = prefs;
|
||||
@ -9574,12 +9715,17 @@ class BaseContent extends (external_React_default()).PureComponent {
|
||||
mayHaveSponsoredTopSites
|
||||
} = prefs;
|
||||
const outerClassName = ["outer-wrapper", isDiscoveryStream && pocketEnabled && "ds-outer-wrapper-search-alignment", isDiscoveryStream && "ds-outer-wrapper-breakpoint-override", prefs.showSearch && this.state.fixedSearch && !noSectionsEnabled && "fixed-search", prefs.showSearch && noSectionsEnabled && "only-search", prefs["logowordmark.alwaysVisible"] && "visible-logo"].filter(v => v).join(" ");
|
||||
if (wallpapersEnabled) {
|
||||
this.updateWallpaper();
|
||||
}
|
||||
return /*#__PURE__*/external_React_default().createElement("div", null, /*#__PURE__*/external_React_default().createElement(CustomizeMenu, {
|
||||
onClose: this.closeCustomizationMenu,
|
||||
onOpen: this.openCustomizationMenu,
|
||||
openPreferences: this.openPreferences,
|
||||
setPref: this.setPref,
|
||||
enabledSections: enabledSections,
|
||||
wallpapersEnabled: wallpapersEnabled,
|
||||
activeWallpaper: activeWallpaper,
|
||||
pocketRegion: pocketRegion,
|
||||
mayHaveSponsoredTopSites: mayHaveSponsoredTopSites,
|
||||
mayHaveSponsoredStories: mayHaveSponsoredStories,
|
||||
@ -9601,7 +9747,7 @@ class BaseContent extends (external_React_default()).PureComponent {
|
||||
locale: props.App.locale,
|
||||
mayHaveSponsoredStories: mayHaveSponsoredStories,
|
||||
firstVisibleTimestamp: this.state.firstVisibleTimestamp
|
||||
})) : /*#__PURE__*/external_React_default().createElement(Sections_Sections, null)), /*#__PURE__*/external_React_default().createElement(ConfirmDialog, null))));
|
||||
})) : /*#__PURE__*/external_React_default().createElement(Sections_Sections, null)), /*#__PURE__*/external_React_default().createElement(ConfirmDialog, null), wallpapersEnabled && this.renderWallpaperAttribution())));
|
||||
}
|
||||
}
|
||||
BaseContent.defaultProps = {
|
||||
@ -9612,7 +9758,8 @@ const Base = (0,external_ReactRedux_namespaceObject.connect)(state => ({
|
||||
Prefs: state.Prefs,
|
||||
Sections: state.Sections,
|
||||
DiscoveryStream: state.DiscoveryStream,
|
||||
Search: state.Search
|
||||
Search: state.Search,
|
||||
Wallpapers: state.Wallpapers
|
||||
}))(_Base);
|
||||
;// CONCATENATED MODULE: ./content-src/lib/detect-user-session-start.mjs
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
|
@ -158,6 +158,15 @@ module.exports = function (config) {
|
||||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
/**
|
||||
* WallpaperFeed.sys.mjs is tested via an xpcshell test
|
||||
*/
|
||||
"lib/WallpaperFeed.sys.mjs": {
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
"content-src/components/DiscoveryStreamComponents/**/*.jsx": {
|
||||
statements: 90.48,
|
||||
lines: 90.48,
|
||||
@ -170,6 +179,15 @@ module.exports = function (config) {
|
||||
functions: 60,
|
||||
branches: 50,
|
||||
},
|
||||
/**
|
||||
* WallpaperSection.jsx is tested via an xpcshell test
|
||||
*/
|
||||
"content-src/components/WallpapersSection/*.jsx": {
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
functions: 0,
|
||||
branches: 0,
|
||||
},
|
||||
"content-src/components/DiscoveryStreamAdmin/*.jsx": {
|
||||
statements: 0,
|
||||
lines: 0,
|
||||
|
@ -36,6 +36,7 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
TelemetryFeed: "resource://activity-stream/lib/TelemetryFeed.sys.mjs",
|
||||
TopSitesFeed: "resource://activity-stream/lib/TopSitesFeed.sys.mjs",
|
||||
TopStoriesFeed: "resource://activity-stream/lib/TopStoriesFeed.sys.mjs",
|
||||
WallpaperFeed: "resource://activity-stream/lib/WallpaperFeed.sys.mjs",
|
||||
});
|
||||
|
||||
// NB: Eagerly load modules that will be loaded/constructed/initialized in the
|
||||
@ -232,6 +233,20 @@ export const PREFS_CONFIG = new Map([
|
||||
value: "topsites,topstories,highlights",
|
||||
},
|
||||
],
|
||||
[
|
||||
"newtabWallpapers.enabled",
|
||||
{
|
||||
title: "Boolean flag to turn wallpaper functionality on and off",
|
||||
value: true,
|
||||
},
|
||||
],
|
||||
[
|
||||
"newtabWallpapers.wallpaper",
|
||||
{
|
||||
title: "Currently set wallpaper",
|
||||
value: "",
|
||||
},
|
||||
],
|
||||
[
|
||||
"improvesearch.noDefaultSearchTile",
|
||||
{
|
||||
@ -524,6 +539,12 @@ const FEEDS_DATA = [
|
||||
title: "Handles new pocket ui for the new tab page",
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
name: "wallpaperfeed",
|
||||
factory: () => new lazy.WallpaperFeed(),
|
||||
title: "Handles fetching and managing wallpaper data from RemoteSettings",
|
||||
value: true,
|
||||
},
|
||||
];
|
||||
|
||||
const FEEDS_CONFIG = new Map();
|
||||
|
114
browser/components/newtab/lib/WallpaperFeed.sys.mjs
Normal file
114
browser/components/newtab/lib/WallpaperFeed.sys.mjs
Normal file
@ -0,0 +1,114 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||
|
||||
const lazy = {};
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
RemoteSettings: "resource://services-settings/remote-settings.sys.mjs",
|
||||
Utils: "resource://services-settings/Utils.sys.mjs",
|
||||
});
|
||||
|
||||
import {
|
||||
actionTypes as at,
|
||||
actionCreators as ac,
|
||||
} from "resource://activity-stream/common/Actions.mjs";
|
||||
|
||||
const PREF_WALLPAPERS_ENABLED =
|
||||
"browser.newtabpage.activity-stream.newtabWallpapers.enabled";
|
||||
|
||||
export class WallpaperFeed {
|
||||
constructor() {
|
||||
this.loaded = false;
|
||||
this.wallpaperClient = "";
|
||||
this.wallpaperDB = "";
|
||||
this.baseAttachmentURL = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* This thin wrapper around global.fetch makes it easier for us to write
|
||||
* automated tests that simulate responses from this fetch.
|
||||
*/
|
||||
fetch(...args) {
|
||||
return fetch(...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* This thin wrapper around lazy.RemoteSettings makes it easier for us to write
|
||||
* automated tests that simulate responses from this fetch.
|
||||
*/
|
||||
RemoteSettings(...args) {
|
||||
return lazy.RemoteSettings(...args);
|
||||
}
|
||||
|
||||
async wallpaperSetup() {
|
||||
const wallpapersEnabled = Services.prefs.getBoolPref(
|
||||
PREF_WALLPAPERS_ENABLED
|
||||
);
|
||||
|
||||
if (wallpapersEnabled) {
|
||||
if (!this.wallpaperClient) {
|
||||
this.wallpaperClient = this.RemoteSettings("newtab-wallpapers");
|
||||
}
|
||||
|
||||
await this.getBaseAttachment();
|
||||
this.wallpaperClient.on("sync", () => this.updateWallpapers());
|
||||
this.updateWallpapers();
|
||||
}
|
||||
}
|
||||
|
||||
async getBaseAttachment() {
|
||||
if (!this.baseAttachmentURL) {
|
||||
const SERVER = lazy.Utils.SERVER_URL;
|
||||
const serverInfo = await (
|
||||
await this.fetch(`${SERVER}/`, {
|
||||
credentials: "omit",
|
||||
})
|
||||
).json();
|
||||
const { base_url } = serverInfo.capabilities.attachments;
|
||||
this.baseAttachmentURL = base_url;
|
||||
}
|
||||
}
|
||||
|
||||
async updateWallpapers() {
|
||||
const records = await this.wallpaperClient.get();
|
||||
if (!records?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.baseAttachmentURL) {
|
||||
await this.getBaseAttachment();
|
||||
}
|
||||
const wallpapers = records.map(record => {
|
||||
return {
|
||||
...record,
|
||||
wallpaperUrl: `${this.baseAttachmentURL}${record.attachment.location}`,
|
||||
};
|
||||
});
|
||||
|
||||
this.store.dispatch(
|
||||
ac.BroadcastToContent({
|
||||
type: at.WALLPAPERS_SET,
|
||||
data: wallpapers,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async onAction(action) {
|
||||
switch (action.type) {
|
||||
case at.INIT:
|
||||
await this.wallpaperSetup();
|
||||
break;
|
||||
case at.UNINIT:
|
||||
break;
|
||||
case at.SYSTEM_TICK:
|
||||
break;
|
||||
case at.PREF_CHANGED:
|
||||
if (action.data.name === "newtabWallpapers.enabled") {
|
||||
await this.wallpaperSetup();
|
||||
}
|
||||
break;
|
||||
case at.WALLPAPERS_SET:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
111
browser/components/newtab/test/xpcshell/test_WallpaperFeed.js
Normal file
111
browser/components/newtab/test/xpcshell/test_WallpaperFeed.js
Normal file
@ -0,0 +1,111 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { WallpaperFeed } = ChromeUtils.importESModule(
|
||||
"resource://activity-stream/lib/WallpaperFeed.sys.mjs"
|
||||
);
|
||||
|
||||
const { actionCreators: ac, actionTypes: at } = ChromeUtils.importESModule(
|
||||
"resource://activity-stream/common/Actions.mjs"
|
||||
);
|
||||
|
||||
ChromeUtils.defineESModuleGetters(this, {
|
||||
Utils: "resource://services-settings/Utils.sys.mjs",
|
||||
sinon: "resource://testing-common/Sinon.sys.mjs",
|
||||
});
|
||||
|
||||
const PREF_WALLPAPERS_ENABLED =
|
||||
"browser.newtabpage.activity-stream.newtabWallpapers.enabled";
|
||||
|
||||
add_task(async function test_construction() {
|
||||
let feed = new WallpaperFeed();
|
||||
|
||||
info("WallpaperFeed constructor should create initial values");
|
||||
|
||||
Assert.ok(feed, "Could construct a WallpaperFeed");
|
||||
Assert.ok(feed.loaded === false, "WallpaperFeed is not loaded");
|
||||
Assert.ok(
|
||||
feed.wallpaperClient === "",
|
||||
"wallpaperClient is initialized as an empty string"
|
||||
);
|
||||
Assert.ok(
|
||||
feed.wallpaperDB === "",
|
||||
"wallpaperDB is initialized as an empty string"
|
||||
);
|
||||
Assert.ok(
|
||||
feed.baseAttachmentURL === "",
|
||||
"baseAttachmentURL is initialized as an empty string"
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_onAction_INIT() {
|
||||
let sandbox = sinon.createSandbox();
|
||||
let feed = new WallpaperFeed();
|
||||
Services.prefs.setBoolPref(PREF_WALLPAPERS_ENABLED, true);
|
||||
const attachment = {
|
||||
attachment: {
|
||||
location: "attachment",
|
||||
},
|
||||
};
|
||||
sandbox.stub(feed, "RemoteSettings").returns({
|
||||
get: () => [attachment],
|
||||
on: () => {},
|
||||
});
|
||||
sandbox.stub(Utils, "SERVER_URL").returns("http://localhost:8888/v1");
|
||||
feed.store = {
|
||||
dispatch: sinon.spy(),
|
||||
};
|
||||
sandbox.stub(feed, "fetch").resolves({
|
||||
json: () => ({
|
||||
capabilities: {
|
||||
attachments: {
|
||||
base_url: "http://localhost:8888/base_url/",
|
||||
},
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
||||
info("WallpaperFeed.onAction INIT should initialize wallpapers");
|
||||
|
||||
await feed.onAction({
|
||||
type: at.INIT,
|
||||
});
|
||||
|
||||
Assert.ok(feed.store.dispatch.calledOnce);
|
||||
Assert.ok(
|
||||
feed.store.dispatch.calledWith(
|
||||
ac.BroadcastToContent({
|
||||
type: at.WALLPAPERS_SET,
|
||||
data: [
|
||||
{
|
||||
...attachment,
|
||||
wallpaperUrl: "http://localhost:8888/base_url/attachment",
|
||||
},
|
||||
],
|
||||
})
|
||||
)
|
||||
);
|
||||
Services.prefs.clearUserPref(PREF_WALLPAPERS_ENABLED);
|
||||
sandbox.restore();
|
||||
});
|
||||
|
||||
add_task(async function test_onAction_PREF_CHANGED() {
|
||||
let sandbox = sinon.createSandbox();
|
||||
let feed = new WallpaperFeed();
|
||||
Services.prefs.setBoolPref(PREF_WALLPAPERS_ENABLED, true);
|
||||
sandbox.stub(feed, "wallpaperSetup").returns();
|
||||
|
||||
info("WallpaperFeed.onAction PREF_CHANGED should call wallpaperSetup");
|
||||
|
||||
feed.onAction({
|
||||
type: at.PREF_CHANGED,
|
||||
data: { name: "newtabWallpapers.enabled" },
|
||||
});
|
||||
|
||||
Assert.ok(feed.wallpaperSetup.calledOnce);
|
||||
|
||||
Services.prefs.clearUserPref(PREF_WALLPAPERS_ENABLED);
|
||||
sandbox.restore();
|
||||
});
|
@ -26,3 +26,5 @@ support-files = ["../schemas/*.schema.json"]
|
||||
["test_TopSitesFeed.js"]
|
||||
|
||||
["test_TopSitesFeed_glean.js"]
|
||||
|
||||
["test_WallpaperFeed.js"]
|
||||
|
@ -272,3 +272,25 @@ newtab-custom-recent-toggle =
|
||||
.description = A selection of recent sites and content
|
||||
newtab-custom-close-button = Close
|
||||
newtab-custom-settings = Manage more settings
|
||||
|
||||
## New Tab Wallpapers
|
||||
|
||||
newtab-wallpaper-title = Wallpapers
|
||||
newtab-wallpaper-reset = Reset to default
|
||||
newtab-wallpaper-light-red-panda = Red panda
|
||||
newtab-wallpaper-light-mountain = White mountain
|
||||
newtab-wallpaper-light-sky = Sky with purple and pink clouds
|
||||
newtab-wallpaper-light-color = Blue, pink and yellow shapes
|
||||
newtab-wallpaper-light-landscape = Blue mist mountain landscape
|
||||
newtab-wallpaper-light-beach = Beach with palm tree
|
||||
newtab-wallpaper-dark-aurora = Aurora Borealis
|
||||
newtab-wallpaper-dark-color = Red and blue shapes
|
||||
newtab-wallpaper-dark-panda = Red panda hidden in forest
|
||||
newtab-wallpaper-dark-sky = City landscape with a night sky
|
||||
newtab-wallpaper-dark-mountain = Landscape mountain
|
||||
newtab-wallpaper-dark-city = Purple city landscape
|
||||
|
||||
# Variables
|
||||
# $author_string (String) - The name of the creator of the photo.
|
||||
# $webpage_string (String) - The name of the webpage where the photo is located.
|
||||
newtab-wallpaper-attribution = Photo by <a data-l10n-name="name-link">{ $author_string }</a> on <a data-l10n-name="webpage-link">{ $webpage_string }</a>
|
||||
|
@ -840,6 +840,13 @@ pocketNewtab:
|
||||
browser.newtabpage.activity-stream.discoverystream.sendToPocket.enabled
|
||||
description: >-
|
||||
Decides what to do when a logged out user click "Save to Pocket" from a Pocket card.
|
||||
wallpapers:
|
||||
type: boolean
|
||||
setPref:
|
||||
branch: user
|
||||
pref: browser.newtabpage.activity-stream.newtabWallpapers.enabled
|
||||
description: >-
|
||||
Turns on and off wallpaper support.
|
||||
recsPersonalized:
|
||||
type: boolean
|
||||
fallbackPref: >-
|
||||
|
Loading…
Reference in New Issue
Block a user