1/* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5import { LinkMenu } from "content-src/components/LinkMenu/LinkMenu"; 6import { ContextMenuButton } from "content-src/components/ContextMenu/ContextMenuButton"; 7import React from "react"; 8 9export class DSLinkMenu extends React.PureComponent { 10 constructor(props) { 11 super(props); 12 this.onMenuUpdate = this.onMenuUpdate.bind(this); 13 this.onMenuShow = this.onMenuShow.bind(this); 14 this.contextMenuButtonRef = React.createRef(); 15 } 16 17 onMenuUpdate(showContextMenu) { 18 if (!showContextMenu) { 19 const dsLinkMenuHostDiv = this.contextMenuButtonRef.current.parentElement; 20 dsLinkMenuHostDiv.parentElement.classList.remove("active", "last-item"); 21 } 22 } 23 24 nextAnimationFrame() { 25 return new Promise(resolve => 26 this.props.windowObj.requestAnimationFrame(resolve) 27 ); 28 } 29 30 async onMenuShow() { 31 const dsLinkMenuHostDiv = this.contextMenuButtonRef.current.parentElement; 32 // Wait for next frame before computing scrollMaxX to allow fluent menu strings to be visible 33 await this.nextAnimationFrame(); 34 if (this.props.windowObj.scrollMaxX > 0) { 35 dsLinkMenuHostDiv.parentElement.classList.add("last-item"); 36 } 37 dsLinkMenuHostDiv.parentElement.classList.add("active"); 38 } 39 40 render() { 41 const { index, dispatch } = this.props; 42 const TOP_STORIES_CONTEXT_MENU_OPTIONS = [ 43 "CheckBookmarkOrArchive", 44 "CheckSavedToPocket", 45 "Separator", 46 "OpenInNewWindow", 47 "OpenInPrivateWindow", 48 "Separator", 49 "BlockUrl", 50 ...(this.props.flightId ? ["ShowPrivacyInfo"] : []), 51 ]; 52 const type = this.props.type || "DISCOVERY_STREAM"; 53 const title = this.props.title || this.props.source; 54 55 return ( 56 <div> 57 <ContextMenuButton 58 refFunction={this.contextMenuButtonRef} 59 tooltip={"newtab-menu-content-tooltip"} 60 tooltipArgs={{ title }} 61 onUpdate={this.onMenuUpdate} 62 > 63 <LinkMenu 64 dispatch={dispatch} 65 index={index} 66 source={type.toUpperCase()} 67 onShow={this.onMenuShow} 68 options={TOP_STORIES_CONTEXT_MENU_OPTIONS} 69 shouldSendImpressionStats={true} 70 site={{ 71 referrer: "https://getpocket.com/recommendations", 72 title: this.props.title, 73 type: this.props.type, 74 url: this.props.url, 75 guid: this.props.id, 76 pocket_id: this.props.pocket_id, 77 shim: this.props.shim, 78 bookmarkGuid: this.props.bookmarkGuid, 79 flight_id: this.props.flightId, 80 }} 81 /> 82 </ContextMenuButton> 83 </div> 84 ); 85 } 86} 87 88DSLinkMenu.defaultProps = { 89 windowObj: window, // Added to support unit tests 90}; 91