/* 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 { actionCreators as ac, actionTypes as at } from "common/Actions.mjs"; import { DiscoveryStreamAdmin } from "content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin"; import { ConfirmDialog } from "content-src/components/ConfirmDialog/ConfirmDialog"; import { connect } from "react-redux"; import { DiscoveryStreamBase } from "content-src/components/DiscoveryStreamBase/DiscoveryStreamBase"; import { ErrorBoundary } from "content-src/components/ErrorBoundary/ErrorBoundary"; import { CustomizeMenu } from "content-src/components/CustomizeMenu/CustomizeMenu"; import React from "react"; import { Search } from "content-src/components/Search/Search"; import { Sections } from "content-src/components/Sections/Sections"; import { Logo } from "content-src/components/Logo/Logo"; import { Weather } from "content-src/components/Weather/Weather"; import { DownloadModalToggle } from "content-src/components/DownloadModalToggle/DownloadModalToggle"; import { Notifications } from "content-src/components/Notifications/Notifications"; import { TopicSelection } from "content-src/components/DiscoveryStreamComponents/TopicSelection/TopicSelection"; import { DownloadMobilePromoHighlight } from "../DiscoveryStreamComponents/FeatureHighlight/DownloadMobilePromoHighlight"; import { WallpaperFeatureHighlight } from "../DiscoveryStreamComponents/FeatureHighlight/WallpaperFeatureHighlight"; import { MessageWrapper } from "content-src/components/MessageWrapper/MessageWrapper"; const VISIBLE = "visible"; const VISIBILITY_CHANGE_EVENT = "visibilitychange"; const PREF_THUMBS_UP_DOWN_ENABLED = "discoverystream.thumbsUpDown.enabled"; const PREF_THUMBS_UP_DOWN_LAYOUT_ENABLED = "discoverystream.thumbsUpDown.searchTopsitesCompact"; const PREF_INFERRED_PERSONALIZATION_SYSTEM = "discoverystream.sections.personalization.inferred.enabled"; const PREF_INFERRED_PERSONALIZATION_USER = "discoverystream.sections.personalization.inferred.user.enabled"; export const PrefsButton = ({ onClick, icon }) => (
{authorDetails.string} {webpage.string}
); } return null; } async updateWallpaper() { const prefs = this.props.Prefs.values; const selectedWallpaper = prefs["newtabWallpapers.wallpaper"]; const { wallpaperList, uploadedWallpaper } = this.props.Wallpapers; let lightWallpaper = {}; let darkWallpaper = {}; if (selectedWallpaper === "custom" && uploadedWallpaper) { // revoke ObjectURL to prevent memory leaks if (this.uploadedWallpaperUrl) { URL.revokeObjectURL(this.uploadedWallpaperUrl); } try { const uploadedWallpaperUrl = URL.createObjectURL(uploadedWallpaper); global.document?.body.style.setProperty( "--newtab-wallpaper", `url(${uploadedWallpaperUrl})` ); global.document?.body.style.setProperty( "--newtab-wallpaper-color", "transparent" ); } catch (e) {} return; } if (wallpaperList) { let wallpaper = wallpaperList.find(wp => wp.title === selectedWallpaper); if (selectedWallpaper && wallpaper) { // if selectedWallpaper exists - we override what light and dark prefs are to match that lightWallpaper = wallpaper; darkWallpaper = wallpaper; } // solid-color-picker-#00d100 const regexRGB = /#([a-fA-F0-9]{6})/; // Override Remote Settings to set custom HEX bg color if (selectedWallpaper.includes("solid-color-picker")) { wallpaper = { theme: wallpaper?.theme || "light", title: "solid-color-picker", category: "solid-colors", solid_color: selectedWallpaper.match(regexRGB)?.[0], }; } const wallpaperColor = wallpaper?.solid_color || ""; global.document?.body.style.setProperty( "--newtab-wallpaper", `url(${wallpaper?.wallpaperUrl || ""})` ); global.document?.body.style.setProperty( "--newtab-wallpaper-color", wallpaperColor || "transparent" ); let wallpaperTheme = ""; // If we have a solid colour set, let's see how dark it is. if (wallpaperColor) { const rgbColors = this.getRGBColors(wallpaperColor); const isColorDark = this.isWallpaperColorDark(rgbColors); wallpaperTheme = isColorDark ? "dark" : "light"; } else { // Grab the contrast of the currently displayed wallpaper. const { theme } = this.state.colorMode === "light" ? lightWallpaper : darkWallpaper; if (theme) { wallpaperTheme = theme; } } this.setState({ wallpaperTheme }); } } shouldShowOMCHighlight(componentId) { const messageData = this.props.Messages?.messageData; if (!messageData || Object.keys(messageData).length === 0) { return false; } return messageData?.content?.messageType === componentId; } toggleDownloadHighlight() { this.setState(prevState => { const override = !( prevState.showDownloadHighlightOverride ?? this.shouldShowOMCHighlight("DownloadMobilePromoHighlight") ); return { showDownloadHighlightOverride: override, }; }); } handleDismissDownloadHighlight() { this.setState({ showDownloadHighlightOverride: false }); } getRGBColors(input) { if (input.length !== 7) { return []; } const r = parseInt(input.substr(1, 2), 16); const g = parseInt(input.substr(3, 2), 16); const b = parseInt(input.substr(5, 2), 16); return [r, g, b]; } isWallpaperColorDark([r, g, b]) { return 0.2125 * r + 0.7154 * g + 0.0721 * b <= 110; } shouldDisplayTopicSelectionModal() { const prefs = this.props.Prefs.values; const pocketEnabled = prefs["feeds.section.topstories"] && prefs["feeds.system.topstories"]; const topicSelectionOnboardingEnabled = prefs["discoverystream.topicSelection.onboarding.enabled"] && pocketEnabled; const maybeShowModal = prefs["discoverystream.topicSelection.onboarding.maybeDisplay"]; const displayTimeout = prefs["discoverystream.topicSelection.onboarding.displayTimeout"]; const lastDisplayed = prefs["discoverystream.topicSelection.onboarding.lastDisplayed"]; const displayCount = prefs["discoverystream.topicSelection.onboarding.displayCount"]; if ( !maybeShowModal || !prefs["discoverystream.topicSelection.enabled"] || !topicSelectionOnboardingEnabled ) { return; } const day = 24 * 60 * 60 * 1000; const now = new Date().getTime(); const timeoutOccured = now - parseFloat(lastDisplayed) > displayTimeout; if (displayCount < 3) { if (displayCount === 0 || timeoutOccured) { this.props.dispatch( ac.BroadcastToContent({ type: at.TOPIC_SELECTION_SPOTLIGHT_OPEN }) ); this.setPref( "discoverystream.topicSelection.onboarding.displayTimeout", day ); } } } // eslint-disable-next-line max-statements, complexity render() { const { props } = this; const { App, DiscoveryStream } = props; const { initialized, customizeMenuVisible } = App; const prefs = props.Prefs.values; const layoutsVariantAEnabled = prefs["newtabLayouts.variant-a"]; const layoutsVariantBEnabled = prefs["newtabLayouts.variant-b"]; const shortcutsRefresh = prefs["newtabShortcuts.refresh"]; const layoutsVariantAorB = layoutsVariantAEnabled || layoutsVariantBEnabled; const activeWallpaper = prefs[`newtabWallpapers.wallpaper`]; const wallpapersEnabled = prefs["newtabWallpapers.enabled"]; const weatherEnabled = prefs.showWeather; const { showTopicSelection } = DiscoveryStream; const mayShowTopicSelection = showTopicSelection && prefs["discoverystream.topicSelection.enabled"]; const { pocketConfig } = prefs; const isDiscoveryStream = props.DiscoveryStream.config && props.DiscoveryStream.config.enabled; let filteredSections = props.Sections.filter( section => section.id !== "topstories" ); let spocMessageVariant = ""; if ( props.App.locale?.startsWith("en-") && pocketConfig?.spocMessageVariant === "variant-c" ) { spocMessageVariant = pocketConfig.spocMessageVariant; } const pocketEnabled = prefs["feeds.section.topstories"] && prefs["feeds.system.topstories"]; const noSectionsEnabled = !prefs["feeds.topsites"] && !pocketEnabled && filteredSections.filter(section => section.enabled).length === 0; const searchHandoffEnabled = prefs["improvesearch.handoffToAwesomebar"]; const enabledSections = { topSitesEnabled: prefs["feeds.topsites"], pocketEnabled: prefs["feeds.section.topstories"], showInferredPersonalizationEnabled: prefs[PREF_INFERRED_PERSONALIZATION_USER], showRecentSavesEnabled: prefs.showRecentSaves, topSitesRowsCount: prefs.topSitesRows, weatherEnabled: prefs.showWeather, }; const pocketRegion = prefs["feeds.system.topstories"]; const mayHaveSponsoredStories = prefs["system.showSponsored"]; const mayHaveInferredPersonalization = prefs[PREF_INFERRED_PERSONALIZATION_SYSTEM]; const mayHaveWeather = prefs["system.showWeather"]; const { mayHaveSponsoredTopSites } = prefs; const supportUrl = prefs["support.url"]; // Mobile Download Promo Pref Checks const mobileDownloadPromoEnabled = prefs["mobileDownloadModal.enabled"]; const mobileDownloadPromoVariantAEnabled = prefs["mobileDownloadModal.variant-a"]; const mobileDownloadPromoVariantBEnabled = prefs["mobileDownloadModal.variant-b"]; const mobileDownloadPromoVariantCEnabled = prefs["mobileDownloadModal.variant-c"]; const mobileDownloadPromoVariantABorC = mobileDownloadPromoVariantAEnabled || mobileDownloadPromoVariantBEnabled || mobileDownloadPromoVariantCEnabled; const mobileDownloadPromoWrapperHeightModifier = prefs["weather.display"] === "detailed" && weatherEnabled && mayHaveWeather ? "is-tall" : ""; const hasThumbsUpDownLayout = prefs["discoverystream.thumbsUpDown.searchTopsitesCompact"]; const hasThumbsUpDown = prefs["discoverystream.thumbsUpDown.enabled"]; const sectionsEnabled = prefs["discoverystream.sections.enabled"]; const topicLabelsEnabled = prefs["discoverystream.topicLabels.enabled"]; const sectionsCustomizeMenuPanelEnabled = prefs["discoverystream.sections.customizeMenuPanel.enabled"]; const sectionsPersonalizationEnabled = prefs["discoverystream.sections.personalization.enabled"]; // Logic to show follow/block topic mgmt panel in Customize panel const mayHavePersonalizedTopicSections = sectionsPersonalizationEnabled && topicLabelsEnabled && sectionsEnabled && sectionsCustomizeMenuPanelEnabled && DiscoveryStream.feeds.loaded; const featureClassName = [ mobileDownloadPromoEnabled && mobileDownloadPromoVariantABorC && "has-mobile-download-promo", // Mobile download promo modal is enabled/visible weatherEnabled && mayHaveWeather && "has-weather", // Weather widget is enabled/visible prefs.showSearch ? "has-search" : "no-search", layoutsVariantAEnabled ? "layout-variant-a" : "", // Layout experiment variant A layoutsVariantBEnabled ? "layout-variant-b" : "", // Layout experiment variant B shortcutsRefresh ? "shortcuts-refresh" : "", // Shortcuts refresh experiment pocketEnabled ? "has-recommended-stories" : "no-recommended-stories", sectionsEnabled ? "has-sections-grid" : "", ] .filter(v => v) .join(" "); 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["feeds.topsites"] && !pocketEnabled && !prefs.showSearch && "only-topsites", noSectionsEnabled && "no-sections", prefs["logowordmark.alwaysVisible"] && "visible-logo", hasThumbsUpDownLayout && hasThumbsUpDown && "thumbs-ui-compact", ] .filter(v => v) .join(" "); if (wallpapersEnabled) { // Add helper class to body if user has a wallpaper selected if (this.state.wallpaperTheme === "light") { global.document?.body.classList.add("lightWallpaper"); global.document?.body.classList.remove("darkWallpaper"); } if (this.state.wallpaperTheme === "dark") { global.document?.body.classList.add("darkWallpaper"); global.document?.body.classList.remove("lightWallpaper"); } } // If state.showDownloadHighlightOverride has value, let it override the logic // Otherwise, defer to OMC message display logic const shouldShowDownloadHighlight = this.state.showDownloadHighlightOverride ?? this.shouldShowOMCHighlight("DownloadMobilePromoHighlight"); return (