diff options
Diffstat (limited to 'browser/components/newtab/content-src/components/LinkMenu/LinkMenu.jsx')
-rw-r--r-- | browser/components/newtab/content-src/components/LinkMenu/LinkMenu.jsx | 110 |
1 files changed, 110 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/components/LinkMenu/LinkMenu.jsx b/browser/components/newtab/content-src/components/LinkMenu/LinkMenu.jsx new file mode 100644 index 0000000000..650a03eb95 --- /dev/null +++ b/browser/components/newtab/content-src/components/LinkMenu/LinkMenu.jsx @@ -0,0 +1,110 @@ +/* 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 } from "common/Actions.sys.mjs"; +import { connect } from "react-redux"; +import { ContextMenu } from "content-src/components/ContextMenu/ContextMenu"; +import { LinkMenuOptions } from "content-src/lib/link-menu-options"; +import React from "react"; + +const DEFAULT_SITE_MENU_OPTIONS = [ + "CheckPinTopSite", + "EditTopSite", + "Separator", + "OpenInNewWindow", + "OpenInPrivateWindow", + "Separator", + "BlockUrl", +]; + +export class _LinkMenu extends React.PureComponent { + getOptions() { + const { props } = this; + const { + site, + index, + source, + isPrivateBrowsingEnabled, + siteInfo, + platform, + userEvent = ac.UserEvent, + } = props; + + // Handle special case of default site + const propOptions = + site.isDefault && !site.searchTopSite && !site.sponsored_position + ? DEFAULT_SITE_MENU_OPTIONS + : props.options; + + const options = propOptions + .map(o => + LinkMenuOptions[o]( + site, + index, + source, + isPrivateBrowsingEnabled, + siteInfo, + platform + ) + ) + .map(option => { + const { action, impression, id, type, userEvent: eventName } = option; + if (!type && id) { + option.onClick = (event = {}) => { + const { ctrlKey, metaKey, shiftKey, button } = event; + // Only send along event info if there's something non-default to send + if (ctrlKey || metaKey || shiftKey || button === 1) { + action.data = Object.assign( + { + event: { ctrlKey, metaKey, shiftKey, button }, + }, + action.data + ); + } + props.dispatch(action); + if (eventName) { + const userEventData = Object.assign( + { + event: eventName, + source, + action_position: index, + value: { card_type: site.flight_id ? "spoc" : "organic" }, + }, + siteInfo + ); + props.dispatch(userEvent(userEventData)); + } + if (impression && props.shouldSendImpressionStats) { + props.dispatch(impression); + } + }; + } + return option; + }); + + // This is for accessibility to support making each item tabbable. + // We want to know which item is the first and which item + // is the last, so we can close the context menu accordingly. + options[0].first = true; + options[options.length - 1].last = true; + return options; + } + + render() { + return ( + <ContextMenu + onUpdate={this.props.onUpdate} + onShow={this.props.onShow} + options={this.getOptions()} + keyboardAccess={this.props.keyboardAccess} + /> + ); + } +} + +const getState = state => ({ + isPrivateBrowsingEnabled: state.Prefs.values.isPrivateBrowsingEnabled, + platform: state.Prefs.values.platform, +}); +export const LinkMenu = connect(getState)(_LinkMenu); |