diff --git a/browser/components/asrouter/modules/PanelTestProvider.sys.mjs b/browser/components/asrouter/modules/PanelTestProvider.sys.mjs index 8ffbc430239f..3bb91a6fb7e0 100644 --- a/browser/components/asrouter/modules/PanelTestProvider.sys.mjs +++ b/browser/components/asrouter/modules/PanelTestProvider.sys.mjs @@ -1553,23 +1553,6 @@ const MESSAGES = () => [ }, groups: [], }, - { - id: "NEWTAB_PERSONALIZATION_MESSAGE", - template: "newtab_message", - content: { - messageType: "PersonalizedCard", - position: 1, - cardTitle: "Personalized Just for You!", - cardMessage: - "We’re customizing your feed to show content that matters to you, while ensuring your privacy is always respected.", - ctaText: "Manage your settings", - linkText: "Learn how we protect and manage data", - }, - trigger: { - id: "newtabMessageCheck", - }, - groups: [], - }, ]; export const PanelTestProvider = { diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/CardSections/CardSections.jsx b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/CardSections/CardSections.jsx index 2a8f119ac326..75498c479835 100644 --- a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/CardSections/CardSections.jsx +++ b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/CardSections/CardSections.jsx @@ -12,7 +12,6 @@ import { SectionContextMenu } from "../SectionContextMenu/SectionContextMenu"; import { InterestPicker } from "../InterestPicker/InterestPicker"; import { AdBanner } from "../AdBanner/AdBanner.jsx"; import { PersonalizedCard } from "../PersonalizedCard/PersonalizedCard"; -import { MessageWrapper } from "content-src/components/MessageWrapper/MessageWrapper"; // Prefs const PREF_SECTIONS_CARDS_ENABLED = "discoverystream.sections.cards.enabled"; @@ -33,6 +32,14 @@ const PREF_BILLBOARD_ENABLED = "newtabAdSize.billboard"; const PREF_LEADERBOARD_ENABLED = "newtabAdSize.leaderboard"; const PREF_LEADERBOARD_POSITION = "newtabAdSize.leaderboard.position"; const PREF_BILLBOARD_POSITION = "newtabAdSize.billboard.position"; +const PREF_INFERRED_PERSONALIZATION_ENABLED = + "discoverystream.sections.personalization.inferred.enabled"; +const PREF_INFERRED_PERSONALIZATION_USER_ENABLED = + "discoverystream.sections.personalization.inferred.user.enabled"; +const PREF_INFERRED_PERSONALIZATION_POSITION = + "discoverystream.sections.personalization.inferred.position"; +const PREF_INFERRED_PERSONALIZATION_BLOCKED = + "discoverystream.sections.personalization.inferred.blocked"; function getLayoutData(responsiveLayouts, index) { let layoutData = { @@ -352,7 +359,6 @@ function CardSections({ const { spocs, sectionPersonalization } = useSelector( state => state.DiscoveryStream ); - const { messageData } = useSelector(state => state.Messages); const personalizationEnabled = prefs[PREF_SECTIONS_PERSONALIZATION_ENABLED]; const interestPickerEnabled = prefs[PREF_INTEREST_PICKER_ENABLED]; @@ -455,22 +461,22 @@ function CardSections({ ); } + const handleDismissP13nCard = () => { + dispatch(ac.SetPref(PREF_INFERRED_PERSONALIZATION_BLOCKED, true)); + }; + function displayP13nCard() { - if (messageData && Object.keys(messageData).length >= 1) { - if (messageData?.content?.messageType === "PersonalizedCard") { - const row = messageData.content.position; - sectionsToRender.splice( - row, - 0, - {}}> - - - ); - } + const row = prefs[PREF_INFERRED_PERSONALIZATION_POSITION]; + const cardBlocked = prefs[PREF_INFERRED_PERSONALIZATION_BLOCKED]; + const cardEnabled = prefs[PREF_INFERRED_PERSONALIZATION_ENABLED]; + const userEnabled = prefs[PREF_INFERRED_PERSONALIZATION_USER_ENABLED]; + + if (!cardBlocked && cardEnabled && userEnabled) { + sectionsToRender.splice( + row, + 0, + + ); } } diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/PersonalizedCard.jsx b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/PersonalizedCard.jsx index 0947841a4948..ad44bebf7bf7 100644 --- a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/PersonalizedCard.jsx +++ b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/PersonalizedCard.jsx @@ -2,34 +2,12 @@ * 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, { useCallback } from "react"; -import { SafeAnchor } from "../SafeAnchor/SafeAnchor"; -import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs"; +import React from "react"; -export const PersonalizedCard = ({ - dispatch, - handleDismiss, - handleClick, - handleBlock, - messageData, -}) => { +export const PersonalizedCard = ({ onDismiss }) => { const wavingFox = "chrome://newtab/content/data/content/assets/waving-fox.svg"; - const onDismiss = useCallback(() => { - handleDismiss(); - handleBlock(); - }, [handleDismiss, handleBlock]); - - const onToggleClick = useCallback( - elementId => { - dispatch({ type: at.SHOW_PERSONALIZE }); - dispatch(ac.UserEvent({ event: "SHOW_PERSONALIZE" })); - handleClick(elementId); - }, - [dispatch, handleClick] - ); - return ( ); diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/_PersonalizedCard.scss b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/_PersonalizedCard.scss index 9a99f7c62a12..ae57c4c7e638 100644 --- a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/_PersonalizedCard.scss +++ b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/PersonalizedCard/_PersonalizedCard.scss @@ -36,7 +36,7 @@ font-weight: var(--font-weight-bold); } - .personalized-card-link { + a { color: var(--link-color); font-size: var(--font-size-small); } @@ -50,7 +50,7 @@ justify-self: initial; } - .personalized-card-link { + a { margin-top: 8px; margin-bottom: 15px; } @@ -76,7 +76,7 @@ width: 195px; } - .personalized-card-link { + a { margin-top: -60px; grid-column: 3; } @@ -106,7 +106,7 @@ width: 220px; } - .personalized-card-link { + a { grid-column: 4; margin-top: -50px; } @@ -125,7 +125,7 @@ margin-inline-end: 40px; } - .personalized-card-link { + a { width: 290px; margin-top: -60px; } diff --git a/browser/extensions/newtab/content-src/components/MessageWrapper/MessageWrapper.jsx b/browser/extensions/newtab/content-src/components/MessageWrapper/MessageWrapper.jsx index 98f1a108258c..8a1f36a35816 100644 --- a/browser/extensions/newtab/content-src/components/MessageWrapper/MessageWrapper.jsx +++ b/browser/extensions/newtab/content-src/components/MessageWrapper/MessageWrapper.jsx @@ -53,7 +53,7 @@ function MessageWrapper({ children, dispatch, hiddenOverride, onDismiss }) { } else { dispatch(ac.AlsoToMain(action)); } - onDismiss?.(); + onDismiss(); }, [dispatch, message, onDismiss]); function handleDismiss() { @@ -93,26 +93,24 @@ function MessageWrapper({ children, dispatch, hiddenOverride, onDismiss }) { } } - if (!message || (!hiddenOverride && message.isHidden)) { - return null; - } - // only display the message if `isHidden` is false return ( -
{ - ref.current = [el]; - }} - className="message-wrapper" - > - {React.cloneElement(children, { - isIntersecting, - handleDismiss, - handleClick, - handleBlock, - handleClose, - })} -
+ (!message.isHidden || hiddenOverride) && ( +
{ + ref.current = [el]; + }} + className="message-wrapper" + > + {React.cloneElement(children, { + isIntersecting, + handleDismiss, + handleClick, + handleBlock, + handleClose, + })} +
+ ) ); } diff --git a/browser/extensions/newtab/css/activity-stream.css b/browser/extensions/newtab/css/activity-stream.css index 433b060965e1..0eb770e844d0 100644 --- a/browser/extensions/newtab/css/activity-stream.css +++ b/browser/extensions/newtab/css/activity-stream.css @@ -8389,7 +8389,7 @@ main section { font-size: var(--font-size-xxlarge); font-weight: var(--font-weight-bold); } -.personalized-card-wrapper .personalized-card-inner .personalized-card-link { +.personalized-card-wrapper .personalized-card-inner a { color: var(--link-color); font-size: var(--font-size-small); } @@ -8401,7 +8401,7 @@ main section { .personalized-card-wrapper .personalized-card-inner img { justify-self: initial; } - .personalized-card-wrapper .personalized-card-inner .personalized-card-link { + .personalized-card-wrapper .personalized-card-inner a { margin-top: 8px; margin-bottom: 15px; } @@ -8423,7 +8423,7 @@ main section { margin-top: -30px; width: 195px; } - .personalized-card-wrapper .personalized-card-inner .personalized-card-link { + .personalized-card-wrapper .personalized-card-inner a { margin-top: -60px; grid-column: 3; } @@ -8448,7 +8448,7 @@ main section { margin-top: initial; width: 220px; } - .personalized-card-wrapper .personalized-card-inner .personalized-card-link { + .personalized-card-wrapper .personalized-card-inner a { grid-column: 4; margin-top: -50px; } @@ -8463,7 +8463,7 @@ main section { .personalized-card-wrapper .personalized-card-inner .personalized-card-cta { margin-inline-end: 40px; } - .personalized-card-wrapper .personalized-card-inner .personalized-card-link { + .personalized-card-wrapper .personalized-card-inner a { width: 290px; margin-top: -60px; } diff --git a/browser/extensions/newtab/data/content/activity-stream.bundle.js b/browser/extensions/newtab/data/content/activity-stream.bundle.js index 5bbf0eff3639..99968264baff 100644 --- a/browser/extensions/newtab/data/content/activity-stream.bundle.js +++ b/browser/extensions/newtab/data/content/activity-stream.bundle.js @@ -10962,29 +10962,10 @@ function InterestPicker({ * You can obtain one at http://mozilla.org/MPL/2.0/. */ - - const PersonalizedCard = ({ - dispatch, - handleDismiss, - handleClick, - handleBlock, - messageData + onDismiss }) => { const wavingFox = "chrome://newtab/content/data/content/assets/waving-fox.svg"; - const onDismiss = (0,external_React_namespaceObject.useCallback)(() => { - handleDismiss(); - handleBlock(); - }, [handleDismiss, handleBlock]); - const onToggleClick = (0,external_React_namespaceObject.useCallback)(elementId => { - dispatch({ - type: actionTypes.SHOW_PERSONALIZE - }); - dispatch(actionCreators.UserEvent({ - event: "SHOW_PERSONALIZE" - })); - handleClick(elementId); - }, [dispatch, handleClick]); return /*#__PURE__*/external_React_default().createElement("aside", { className: "personalized-card-wrapper" }, /*#__PURE__*/external_React_default().createElement("div", { @@ -10999,131 +10980,13 @@ const PersonalizedCard = ({ }, /*#__PURE__*/external_React_default().createElement("img", { src: wavingFox, alt: "" - }), /*#__PURE__*/external_React_default().createElement("h2", null, messageData.content.cardTitle), /*#__PURE__*/external_React_default().createElement("p", null, messageData.content.cardMessage), /*#__PURE__*/external_React_default().createElement("moz-button", { + }), /*#__PURE__*/external_React_default().createElement("h2", null, "Personalized Just for You"), /*#__PURE__*/external_React_default().createElement("p", null, "We\u2019re customizing your feed to show content that matters to you, while ensuring your privacy is always respected."), /*#__PURE__*/external_React_default().createElement("moz-button", { type: "primary", - class: "personalized-card-cta", - onClick: () => onToggleClick("open-personalization-panel") - }, messageData.content.ctaText), /*#__PURE__*/external_React_default().createElement(SafeAnchor, { - className: "personalized-card-link", - dispatch: dispatch, - url: "https://www.mozilla.org/en-US/privacy/firefox/#notice", - onLinkClick: () => { - handleClick("link-click"); - } - }, messageData.content.linkText))); + class: "personalized-card-cta" + }, "Manage your settings"), /*#__PURE__*/external_React_default().createElement("a", { + href: "https://www.mozilla.org/en-US/privacy/firefox/#notice" + }, "Learn how we protect and manage data"))); }; -;// CONCATENATED MODULE: ./content-src/components/MessageWrapper/MessageWrapper.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/. */ - - - - - -function MessageWrapper({ - children, - dispatch, - hiddenOverride, - onDismiss -}) { - const message = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Messages); - const [isIntersecting, setIsIntersecting] = (0,external_React_namespaceObject.useState)(false); - const [hasRun, setHasRun] = (0,external_React_namespaceObject.useState)(); - const handleIntersection = (0,external_React_namespaceObject.useCallback)(() => { - setIsIntersecting(true); - const isVisible = document?.visibilityState && document.visibilityState === "visible"; - // only send impression if messageId is defined and tab is visible - if (isVisible && message.messageData.id) { - setHasRun(true); - dispatch(actionCreators.AlsoToMain({ - type: actionTypes.MESSAGE_IMPRESSION, - data: message.messageData - })); - } - }, [dispatch, message]); - (0,external_React_namespaceObject.useEffect)(() => { - const handleVisibilityChange = () => { - if (document.visibilityState === "visible" && !hasRun) { - handleIntersection(); - } - }; - document.addEventListener("visibilitychange", handleVisibilityChange); - return () => { - document.removeEventListener("visibilitychange", handleVisibilityChange); - }; - }, [handleIntersection, hasRun]); - const ref = useIntersectionObserver(handleIntersection); - const handleClose = (0,external_React_namespaceObject.useCallback)(() => { - const action = { - type: actionTypes.MESSAGE_TOGGLE_VISIBILITY, - data: true - }; - if (message.portID) { - dispatch(actionCreators.OnlyToOneContent(action, message.portID)); - } else { - dispatch(actionCreators.AlsoToMain(action)); - } - onDismiss?.(); - }, [dispatch, message, onDismiss]); - function handleDismiss() { - const { - id - } = message.messageData; - if (id) { - dispatch(actionCreators.OnlyToMain({ - type: actionTypes.MESSAGE_DISMISS, - data: { - message: message.messageData - } - })); - } - handleClose(); - } - function handleBlock() { - const { - id - } = message.messageData; - if (id) { - dispatch(actionCreators.OnlyToMain({ - type: actionTypes.MESSAGE_BLOCK, - data: id - })); - } - } - function handleClick(elementId) { - const { - id - } = message.messageData; - if (id) { - dispatch(actionCreators.OnlyToMain({ - type: actionTypes.MESSAGE_CLICK, - data: { - message: message.messageData, - source: elementId || "" - } - })); - } - } - if (!message || !hiddenOverride && message.isHidden) { - return null; - } - - // only display the message if `isHidden` is false - return /*#__PURE__*/external_React_default().createElement("div", { - ref: el => { - ref.current = [el]; - }, - className: "message-wrapper" - }, /*#__PURE__*/external_React_default().cloneElement(children, { - isIntersecting, - handleDismiss, - handleClick, - handleBlock, - handleClose - })); -} - ;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/CardSections/CardSections.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 @@ -11140,7 +11003,6 @@ function MessageWrapper({ - // Prefs const CardSections_PREF_SECTIONS_CARDS_ENABLED = "discoverystream.sections.cards.enabled"; const PREF_SECTIONS_CARDS_THUMBS_UP_DOWN_ENABLED = "discoverystream.sections.cards.thumbsUpDown.enabled"; @@ -11156,6 +11018,10 @@ const CardSections_PREF_BILLBOARD_ENABLED = "newtabAdSize.billboard"; const CardSections_PREF_LEADERBOARD_ENABLED = "newtabAdSize.leaderboard"; const CardSections_PREF_LEADERBOARD_POSITION = "newtabAdSize.leaderboard.position"; const CardSections_PREF_BILLBOARD_POSITION = "newtabAdSize.billboard.position"; +const PREF_INFERRED_PERSONALIZATION_ENABLED = "discoverystream.sections.personalization.inferred.enabled"; +const PREF_INFERRED_PERSONALIZATION_USER_ENABLED = "discoverystream.sections.personalization.inferred.user.enabled"; +const PREF_INFERRED_PERSONALIZATION_POSITION = "discoverystream.sections.personalization.inferred.position"; +const PREF_INFERRED_PERSONALIZATION_BLOCKED = "discoverystream.sections.personalization.inferred.blocked"; function getLayoutData(responsiveLayouts, index) { let layoutData = { classNames: [], @@ -11436,9 +11302,6 @@ function CardSections({ spocs, sectionPersonalization } = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.DiscoveryStream); - const { - messageData - } = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Messages); const personalizationEnabled = prefs[PREF_SECTIONS_PERSONALIZATION_ENABLED]; const interestPickerEnabled = prefs[PREF_INTEREST_PICKER_ENABLED]; @@ -11512,19 +11375,19 @@ function CardSections({ receivedFeedRank: interestPicker.receivedFeedRank })); } + const handleDismissP13nCard = () => { + dispatch(actionCreators.SetPref(PREF_INFERRED_PERSONALIZATION_BLOCKED, true)); + }; function displayP13nCard() { - if (messageData && Object.keys(messageData).length >= 1) { - if (messageData?.content?.messageType === "PersonalizedCard") { - const row = messageData.content.position; - sectionsToRender.splice(row, 0, /*#__PURE__*/external_React_default().createElement(MessageWrapper, { - dispatch: dispatch, - onDismiss: () => {} - }, /*#__PURE__*/external_React_default().createElement(PersonalizedCard, { - position: row, - dispatch: dispatch, - messageData: messageData - }))); - } + const row = prefs[PREF_INFERRED_PERSONALIZATION_POSITION]; + const cardBlocked = prefs[PREF_INFERRED_PERSONALIZATION_BLOCKED]; + const cardEnabled = prefs[PREF_INFERRED_PERSONALIZATION_ENABLED]; + const userEnabled = prefs[PREF_INFERRED_PERSONALIZATION_USER_ENABLED]; + if (!cardBlocked && cardEnabled && userEnabled) { + sectionsToRender.splice(row, 0, /*#__PURE__*/external_React_default().createElement(PersonalizedCard, { + row: row, + onDismiss: handleDismissP13nCard + })); } } displayP13nCard(); @@ -14267,6 +14130,115 @@ function WallpaperFeatureHighlight({ outsideClickCallback: handleDismiss })); } +;// CONCATENATED MODULE: ./content-src/components/MessageWrapper/MessageWrapper.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/. */ + + + + + +function MessageWrapper({ + children, + dispatch, + hiddenOverride, + onDismiss +}) { + const message = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Messages); + const [isIntersecting, setIsIntersecting] = (0,external_React_namespaceObject.useState)(false); + const [hasRun, setHasRun] = (0,external_React_namespaceObject.useState)(); + const handleIntersection = (0,external_React_namespaceObject.useCallback)(() => { + setIsIntersecting(true); + const isVisible = document?.visibilityState && document.visibilityState === "visible"; + // only send impression if messageId is defined and tab is visible + if (isVisible && message.messageData.id) { + setHasRun(true); + dispatch(actionCreators.AlsoToMain({ + type: actionTypes.MESSAGE_IMPRESSION, + data: message.messageData + })); + } + }, [dispatch, message]); + (0,external_React_namespaceObject.useEffect)(() => { + const handleVisibilityChange = () => { + if (document.visibilityState === "visible" && !hasRun) { + handleIntersection(); + } + }; + document.addEventListener("visibilitychange", handleVisibilityChange); + return () => { + document.removeEventListener("visibilitychange", handleVisibilityChange); + }; + }, [handleIntersection, hasRun]); + const ref = useIntersectionObserver(handleIntersection); + const handleClose = (0,external_React_namespaceObject.useCallback)(() => { + const action = { + type: actionTypes.MESSAGE_TOGGLE_VISIBILITY, + data: true + }; + if (message.portID) { + dispatch(actionCreators.OnlyToOneContent(action, message.portID)); + } else { + dispatch(actionCreators.AlsoToMain(action)); + } + onDismiss(); + }, [dispatch, message, onDismiss]); + function handleDismiss() { + const { + id + } = message.messageData; + if (id) { + dispatch(actionCreators.OnlyToMain({ + type: actionTypes.MESSAGE_DISMISS, + data: { + message: message.messageData + } + })); + } + handleClose(); + } + function handleBlock() { + const { + id + } = message.messageData; + if (id) { + dispatch(actionCreators.OnlyToMain({ + type: actionTypes.MESSAGE_BLOCK, + data: id + })); + } + } + function handleClick(elementId) { + const { + id + } = message.messageData; + if (id) { + dispatch(actionCreators.OnlyToMain({ + type: actionTypes.MESSAGE_CLICK, + data: { + message: message.messageData, + source: elementId || "" + } + })); + } + } + + // only display the message if `isHidden` is false + return (!message.isHidden || hiddenOverride) && /*#__PURE__*/external_React_default().createElement("div", { + ref: el => { + ref.current = [el]; + }, + className: "message-wrapper" + }, /*#__PURE__*/external_React_default().cloneElement(children, { + isIntersecting, + handleDismiss, + handleClick, + handleBlock, + handleClose + })); +} + ;// CONCATENATED MODULE: ./content-src/components/Base/Base.jsx function Base_extends() { Base_extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return Base_extends.apply(this, arguments); } /* This Source Code Form is subject to the terms of the Mozilla Public diff --git a/browser/extensions/newtab/karma.mc.config.js b/browser/extensions/newtab/karma.mc.config.js index ea09c74d7d32..07f7650c1b6e 100644 --- a/browser/extensions/newtab/karma.mc.config.js +++ b/browser/extensions/newtab/karma.mc.config.js @@ -230,10 +230,10 @@ module.exports = function (config) { }, "content-src/components/DiscoveryStreamComponents/CardSections/CardSections.jsx": { - statements: 84.55, - lines: 84.03, + statements: 86.05, + lines: 85.48, functions: 79.31, - branches: 53.62, + branches: 54.41, }, "content-src/components/DiscoveryStreamComponents/SectionContextMenu/SectionContextMenu.jsx": {