/* 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 { batch } from "react-redux"; import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs"; import { SectionsMgmtPanel } from "../SectionsMgmtPanel/SectionsMgmtPanel"; import { WallpaperCategories } from "../../WallpaperCategories/WallpaperCategories"; // @nova-cleanup(move-directory): Update import path after WidgetsManagementPanel moves to components/CustomizeMenu/ import { WidgetsManagementPanel } from "content-src/components/Nova/CustomizeMenu/WidgetsManagementPanel/WidgetsManagementPanel"; export class ContentSection extends React.PureComponent { constructor(props) { super(props); this.onPreferenceSelect = this.onPreferenceSelect.bind(this); // Refs are necessary for dynamically measuring drawer heights for slide animations this.topSitesDrawerRef = React.createRef(); this.pocketDrawerRef = React.createRef(); this.widgetsMgmtDrawerRef = React.createRef(); } inputUserEvent(eventSource, eventValue) { batch(() => { this.props.dispatch( ac.UserEvent({ event: "PREF_CHANGED", source: eventSource, value: { status: eventValue, menu_source: "CUSTOMIZE_MENU" }, }) ); // Dispatch unified widget telemetry for widget toggles. // Map the event source from the customize panel to the widget name // for the unified telemetry event. let widgetName; switch (eventSource) { case "WEATHER": widgetName = "weather"; break; case "WIDGET_LISTS": widgetName = "lists"; break; case "WIDGET_TIMER": widgetName = "focus_timer"; break; case "WIDGET_CLOCKS": widgetName = "clocks"; break; case "WIDGET_PRIVACY": widgetName = "privacy"; break; case "WIDGET_CROSSWORD": widgetName = "crossword"; break; case "WIDGET_STOCKS": widgetName = "stocks"; break; case "WIDGET_PICTURE_OF_THE_DAY": widgetName = "picture_of_the_day"; break; } if (widgetName) { const { widgetsMaximized, widgetsMayBeMaximized } = this.props.enabledWidgets; let widgetSize; if (widgetName === "weather") { if ( this.props.mayHaveWeatherForecast && this.props.weatherDisplay === "detailed" ) { widgetSize = widgetsMayBeMaximized && !widgetsMaximized ? "medium" : "large"; } else { widgetSize = "small"; } } else { widgetSize = widgetsMayBeMaximized && !widgetsMaximized ? "medium" : "large"; } const data = { widget_name: widgetName, widget_source: "customize_panel", enabled: eventValue, widget_size: widgetSize, }; this.props.dispatch( ac.OnlyToMain({ type: at.WIDGETS_ENABLED, data, }) ); } }); } onPreferenceSelect(e) { // eventSource: WALLPAPERS | WEATHER | TOP_SITES | TOP_STORIES | WIDGET_LISTS | WIDGET_TIMER const { preference, eventSource } = e.target.dataset; let value; if (e.target.nodeName === "MOZ-SELECT") { value = parseInt(e.target.value, 10); } else if ( e.target.nodeName === "INPUT" || e.target.nodeName === "MOZ-CHECKBOX" ) { value = e.target.checked; if (eventSource) { this.inputUserEvent(eventSource, value); } } else if (e.target.nodeName === "MOZ-TOGGLE") { value = e.target.pressed; if (eventSource) { this.inputUserEvent(eventSource, value); } } this.props.setPref(preference, value); } componentDidMount() { this.setDrawerMargins(); } componentDidUpdate() { this.setDrawerMargins(); } setDrawerMargins() { this.setDrawerMargin( `TOP_SITES`, this.props.enabledSections.topSitesEnabled ); this.setDrawerMargin( `TOP_STORIES`, this.props.enabledSections.pocketEnabled ); this.setDrawerMargin(`WIDGETS`, this.props.widgetsEnabled); } setDrawerMargin(drawerID, isOpen) { let drawerRef; switch (drawerID) { case `TOP_SITES`: drawerRef = this.topSitesDrawerRef.current; break; case `TOP_STORIES`: drawerRef = this.pocketDrawerRef.current; break; case `WIDGETS`: drawerRef = this.widgetsMgmtDrawerRef.current; break; default: return; } if (drawerRef) { // Use measured height if valid, otherwise use a large fallback // since overflow:hidden on the parent safely hides the drawer let drawerHeight = drawerRef.offsetHeight || 100; if (isOpen) { // @nova-cleanup(remove-conditional): Remove novaEnabled check, keep the marginTop assignment drawerRef.style.marginTop = this.props.novaEnabled ? "" : "var(--space-small)"; } else { drawerRef.style.marginTop = `-${drawerHeight + 3}px`; } } } render() { const { enabledSections, enabledWidgets, pocketRegion, mayHaveInferredPersonalization, mayHaveWeather, mayHaveWidgets, mayHaveTimerWidget, mayHaveListsWidget, mayHaveSportsWidget, mayHaveClocksWidget, mayHavePrivacyWidget, mayHaveCrosswordWidget, mayHaveStocksWidget, mayHavePictureOfTheDayWidget, mayHaveWeatherForecast, openPreferences, wallpapersUserEnabled, activeWallpaper, setPref, mayHaveTopicSections, weatherDisplay, exitEventFired, onSubpanelToggle, toggleSectionsMgmtPanel, showSectionsMgmtPanel, // @nova-cleanup(remove-conditional): Remove novaEnabled novaEnabled, wallpapersEnabled, toggleWidgetsManagementPanel, showWidgetsManagementPanel, widgetsEnabled, } = this.props; const { topSitesEnabled, pocketEnabled, weatherEnabled, showInferredPersonalizationEnabled, topSitesRowsCount, } = enabledSections; const { timerEnabled, listsEnabled, clocksEnabled, privacyEnabled, crosswordEnabled, stocksEnabled, pictureOfTheDayEnabled, } = enabledWidgets; // @nova-cleanup(remove-conditional): Remove novaEnabled check and newtab-custom-stories-toggle, default to newtab-recommended-stories-toggle let pocketToggleL10nId; if (mayHaveInferredPersonalization) { pocketToggleL10nId = "newtab-custom-stories-personalized-toggle"; } else if (novaEnabled) { pocketToggleL10nId = "newtab-recommended-stories-toggle"; } else { pocketToggleL10nId = "newtab-custom-stories-toggle"; } // @nova-cleanup(remove-conditional): This conditional adds the toggle for wallpaper visibility. return ( <>