140 lines
4.3 KiB
JavaScript
140 lines
4.3 KiB
JavaScript
/* 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/. */
|
|
|
|
import React, { useState } from "react";
|
|
import { actionCreators as ac } from "common/Actions.mjs";
|
|
import { LinkMenu } from "../../LinkMenu/LinkMenu";
|
|
|
|
/**
|
|
* A context menu for IAB banners (e.g. billboard, leaderboard).
|
|
*
|
|
* Note: MREC ad formats and sponsored stories share the context menu with
|
|
* other cards: make sure you also look at DSLinkMenu component
|
|
* to keep any updates to ad-related context menu items in sync.
|
|
*
|
|
* @param dispatch
|
|
* @param spoc
|
|
* @param position
|
|
* @param type
|
|
* @param showAdReporting
|
|
* @returns {Element}
|
|
* @constructor
|
|
*/
|
|
export function AdBannerContextMenu({
|
|
dispatch,
|
|
spoc,
|
|
position,
|
|
type,
|
|
showAdReporting,
|
|
}) {
|
|
const ADBANNER_CONTEXT_MENU_OPTIONS = [
|
|
"BlockAdUrl",
|
|
...(showAdReporting ? ["ReportAd"] : []),
|
|
"ManageSponsoredContent",
|
|
"OurSponsorsAndYourPrivacy",
|
|
];
|
|
|
|
const [showContextMenu, setShowContextMenu] = useState(false);
|
|
const [contextMenuClassNames, setContextMenuClassNames] =
|
|
useState("ads-context-menu");
|
|
|
|
// The keyboard access parameter is passed down to LinkMenu component
|
|
// that uses it to focus on the first context menu option for accessibility.
|
|
const [isKeyboardAccess, setIsKeyboardAccess] = useState(false);
|
|
|
|
/**
|
|
* Toggles the style fix for context menu hover/active styles.
|
|
* This allows us to have unobtrusive, transparent button background by default,
|
|
* yet flip it over to semi-transparent grey when the menu is visible.
|
|
*
|
|
* @param contextMenuOpen
|
|
*/
|
|
const toggleContextMenuStyleSwitch = contextMenuOpen => {
|
|
if (contextMenuOpen) {
|
|
setContextMenuClassNames("ads-context-menu context-menu-open");
|
|
} else {
|
|
setContextMenuClassNames("ads-context-menu");
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Toggles the context menu to open or close. Sets state depending on whether
|
|
* the context menu is accessed by mouse or keyboard.
|
|
*
|
|
* @param isKeyBoard
|
|
*/
|
|
const toggleContextMenu = isKeyBoard => {
|
|
toggleContextMenuStyleSwitch(!showContextMenu);
|
|
setShowContextMenu(!showContextMenu);
|
|
setIsKeyboardAccess(isKeyBoard);
|
|
};
|
|
|
|
const onClick = e => {
|
|
e.preventDefault();
|
|
toggleContextMenu(false);
|
|
};
|
|
|
|
const onKeyDown = e => {
|
|
if (e.key === "Enter" || e.key === " ") {
|
|
e.preventDefault();
|
|
toggleContextMenu(true);
|
|
}
|
|
};
|
|
|
|
const onUpdate = () => {
|
|
toggleContextMenuStyleSwitch(!showContextMenu);
|
|
setShowContextMenu(!showContextMenu);
|
|
};
|
|
|
|
return (
|
|
<div className="ads-context-menu-wrapper">
|
|
<div className={contextMenuClassNames}>
|
|
<moz-button
|
|
type="icon"
|
|
size="default"
|
|
data-l10n-id="newtab-menu-content-tooltip"
|
|
data-l10n-args={JSON.stringify({
|
|
title: spoc.title || spoc.sponsor || spoc.alt_text,
|
|
})}
|
|
iconsrc="chrome://global/skin/icons/more.svg"
|
|
onClick={onClick}
|
|
onKeyDown={onKeyDown}
|
|
/>
|
|
{showContextMenu && (
|
|
<LinkMenu
|
|
onUpdate={onUpdate}
|
|
dispatch={dispatch}
|
|
keyboardAccess={isKeyboardAccess}
|
|
options={ADBANNER_CONTEXT_MENU_OPTIONS}
|
|
shouldSendImpressionStats={true}
|
|
userEvent={ac.DiscoveryStreamUserEvent}
|
|
site={{
|
|
// Props we want to pass on for new ad types that come from Unified Ads API
|
|
block_key: spoc.block_key,
|
|
fetchTimestamp: spoc.fetchTimestamp,
|
|
flight_id: spoc.flight_id,
|
|
format: spoc.format,
|
|
id: spoc.id,
|
|
guid: spoc.guid,
|
|
card_type: "spoc",
|
|
// required to record telemetry for an action, see handleBlockUrl in TelemetryFeed.sys.mjs
|
|
is_pocket_card: true,
|
|
position,
|
|
sponsor: spoc.sponsor,
|
|
title: spoc.title,
|
|
url: spoc.url || spoc.shim.url,
|
|
personalization_models: spoc.personalization_models,
|
|
priority: spoc.priority,
|
|
score: spoc.score,
|
|
alt_text: spoc.alt_text,
|
|
shim: spoc.shim,
|
|
}}
|
|
index={position}
|
|
source={type.toUpperCase()}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|