From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../content-src/components/TopSites/TopSites.jsx | 213 +++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 browser/components/newtab/content-src/components/TopSites/TopSites.jsx (limited to 'browser/components/newtab/content-src/components/TopSites/TopSites.jsx') diff --git a/browser/components/newtab/content-src/components/TopSites/TopSites.jsx b/browser/components/newtab/content-src/components/TopSites/TopSites.jsx new file mode 100644 index 0000000000..fd1e3048a5 --- /dev/null +++ b/browser/components/newtab/content-src/components/TopSites/TopSites.jsx @@ -0,0 +1,213 @@ +/* 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.sys.mjs"; +import { MIN_RICH_FAVICON_SIZE, TOP_SITES_SOURCE } from "./TopSitesConstants"; +import { CollapsibleSection } from "content-src/components/CollapsibleSection/CollapsibleSection"; +import { ComponentPerfTimer } from "content-src/components/ComponentPerfTimer/ComponentPerfTimer"; +import { connect } from "react-redux"; +import { ModalOverlayWrapper } from "../../asrouter/components/ModalOverlay/ModalOverlay"; +import React from "react"; +import { SearchShortcutsForm } from "./SearchShortcutsForm"; +import { TOP_SITES_MAX_SITES_PER_ROW } from "common/Reducers.sys.mjs"; +import { TopSiteForm } from "./TopSiteForm"; +import { TopSiteList } from "./TopSite"; + +function topSiteIconType(link) { + if (link.customScreenshotURL) { + return "custom_screenshot"; + } + if (link.tippyTopIcon || link.faviconRef === "tippytop") { + return "tippytop"; + } + if (link.faviconSize >= MIN_RICH_FAVICON_SIZE) { + return "rich_icon"; + } + if (link.screenshot) { + return "screenshot"; + } + return "no_image"; +} + +/** + * Iterates through TopSites and counts types of images. + * @param acc Accumulator for reducer. + * @param topsite Entry in TopSites. + */ +function countTopSitesIconsTypes(topSites) { + const countTopSitesTypes = (acc, link) => { + acc[topSiteIconType(link)]++; + return acc; + }; + + return topSites.reduce(countTopSitesTypes, { + custom_screenshot: 0, + screenshot: 0, + tippytop: 0, + rich_icon: 0, + no_image: 0, + }); +} + +export class _TopSites extends React.PureComponent { + constructor(props) { + super(props); + this.onEditFormClose = this.onEditFormClose.bind(this); + this.onSearchShortcutsFormClose = + this.onSearchShortcutsFormClose.bind(this); + } + + /** + * Dispatch session statistics about the quality of TopSites icons and pinned count. + */ + _dispatchTopSitesStats() { + const topSites = this._getVisibleTopSites().filter( + topSite => topSite !== null && topSite !== undefined + ); + const topSitesIconsStats = countTopSitesIconsTypes(topSites); + const topSitesPinned = topSites.filter(site => !!site.isPinned).length; + const searchShortcuts = topSites.filter( + site => !!site.searchTopSite + ).length; + // Dispatch telemetry event with the count of TopSites images types. + this.props.dispatch( + ac.AlsoToMain({ + type: at.SAVE_SESSION_PERF_DATA, + data: { + topsites_icon_stats: topSitesIconsStats, + topsites_pinned: topSitesPinned, + topsites_search_shortcuts: searchShortcuts, + }, + }) + ); + } + + /** + * Return the TopSites that are visible based on prefs and window width. + */ + _getVisibleTopSites() { + // We hide 2 sites per row when not in the wide layout. + let sitesPerRow = TOP_SITES_MAX_SITES_PER_ROW; + // $break-point-widest = 1072px (from _variables.scss) + if (!global.matchMedia(`(min-width: 1072px)`).matches) { + sitesPerRow -= 2; + } + return this.props.TopSites.rows.slice( + 0, + this.props.TopSitesRows * sitesPerRow + ); + } + + componentDidUpdate() { + this._dispatchTopSitesStats(); + } + + componentDidMount() { + this._dispatchTopSitesStats(); + } + + onEditFormClose() { + this.props.dispatch( + ac.UserEvent({ + source: TOP_SITES_SOURCE, + event: "TOP_SITES_EDIT_CLOSE", + }) + ); + this.props.dispatch({ type: at.TOP_SITES_CANCEL_EDIT }); + } + + onSearchShortcutsFormClose() { + this.props.dispatch( + ac.UserEvent({ + source: TOP_SITES_SOURCE, + event: "SEARCH_EDIT_CLOSE", + }) + ); + this.props.dispatch({ type: at.TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL }); + } + + render() { + const { props } = this; + const { editForm, showSearchShortcutsForm } = props.TopSites; + const extraMenuOptions = ["AddTopSite"]; + const colors = props.Prefs.values["newNewtabExperience.colors"]; + + if (props.Prefs.values["improvesearch.topSiteSearchShortcuts"]) { + extraMenuOptions.push("AddSearchShortcut"); + } + + return ( + + + +
+ {editForm && ( +
+ + + +
+ )} + {showSearchShortcutsForm && ( +
+ + + +
+ )} +
+
+
+ ); + } +} + +export const TopSites = connect((state, props) => ({ + TopSites: state.TopSites, + Prefs: state.Prefs, + TopSitesRows: state.Prefs.values.topSitesRows, +}))(_TopSites); -- cgit v1.2.3