@@ -14,12 +14,17 @@ import { getProfileUsesMultipleStackTypes } from 'firefox-profiler/selectors/pro
1414import { PanelSearch } from './PanelSearch' ;
1515import { StackImplementationSetting } from 'firefox-profiler/components/shared/StackImplementationSetting' ;
1616import { MarkerFiltersContextMenu } from './MarkerFiltersContextMenu' ;
17+ import { MarkerCopyTableContextMenu } from './MarkerCopyTableContextMenu' ;
1718
1819import type { ConnectedProps } from 'firefox-profiler/utils/connect' ;
1920
2021import 'firefox-profiler/components/shared/PanelSettingsList.css' ;
2122import './MarkerSettings.css' ;
2223
24+ type OwnProps = {
25+ readonly copyTable ?: ( format : string ) => void ;
26+ } ;
27+
2328type StateProps = {
2429 readonly searchString : string ;
2530 readonly allowSwitchingStackType : boolean ;
@@ -29,7 +34,7 @@ type DispatchProps = {
2934 readonly changeMarkersSearchString : typeof changeMarkersSearchString ;
3035} ;
3136
32- type Props = ConnectedProps < { } , StateProps , DispatchProps > ;
37+ type Props = ConnectedProps < OwnProps , StateProps , DispatchProps > ;
3338
3439type State = {
3540 readonly isMarkerFiltersMenuVisible : boolean ;
@@ -39,12 +44,16 @@ type State = {
3944 // Otherwise, if we check this in onClick event, the state will always be
4045 // `false` since the library already hid it on mousedown.
4146 readonly isFilterMenuVisibleOnMouseDown : boolean ;
47+ readonly isMarkerCopyTableMenuVisible : boolean ;
48+ readonly isCopyTableMenuVisibleOnMouseDown : boolean ;
4249} ;
4350
4451class MarkerSettingsImpl extends PureComponent < Props , State > {
4552 override state = {
4653 isMarkerFiltersMenuVisible : false ,
4754 isFilterMenuVisibleOnMouseDown : false ,
55+ isMarkerCopyTableMenuVisible : false ,
56+ isCopyTableMenuVisibleOnMouseDown : false ,
4857 } ;
4958
5059 _onSearch = ( value : string ) => {
@@ -72,6 +81,36 @@ class MarkerSettingsImpl extends PureComponent<Props, State> {
7281 } ) ;
7382 } ;
7483
84+ _onClickToggleCopyTableMenu = ( event : React . MouseEvent < HTMLElement > ) => {
85+ const { isCopyTableMenuVisibleOnMouseDown } = this . state ;
86+ if ( isCopyTableMenuVisibleOnMouseDown ) {
87+ // Do nothing as we would like to hide the menu if the menu was already visible on mouse down.
88+ return ;
89+ }
90+
91+ const rect = event . currentTarget . getBoundingClientRect ( ) ;
92+ // FIXME: Currently we assume that the context menu is 250px wide, but ideally
93+ // we should get the real width. It's not so easy though, because the context
94+ // menu is not rendered yet.
95+ const isRightAligned = rect . right > window . innerWidth - 250 ;
96+
97+ showMenu ( {
98+ data : null ,
99+ id : 'MarkerCopyTableContextMenu' ,
100+ position : { x : isRightAligned ? rect . right : rect . left , y : rect . bottom } ,
101+ target : event . target ,
102+ } ) ;
103+ } ;
104+
105+ _onCopyTable = ( format : string ) => {
106+ const { copyTable } = this . props ;
107+ if ( ! copyTable ) {
108+ return ;
109+ }
110+
111+ copyTable ( format ) ;
112+ } ;
113+
75114 _onShowFiltersContextMenu = ( ) => {
76115 this . setState ( { isMarkerFiltersMenuVisible : true } ) ;
77116 } ;
@@ -80,15 +119,30 @@ class MarkerSettingsImpl extends PureComponent<Props, State> {
80119 this . setState ( { isMarkerFiltersMenuVisible : false } ) ;
81120 } ;
82121
122+ _onShowCopyTableContextMenu = ( ) => {
123+ this . setState ( { isMarkerCopyTableMenuVisible : true } ) ;
124+ } ;
125+
126+ _onHideCopyTableContextMenu = ( ) => {
127+ this . setState ( { isMarkerCopyTableMenuVisible : false } ) ;
128+ } ;
129+
83130 _onMouseDownToggleFilterButton = ( ) => {
84131 this . setState ( ( state ) => ( {
85132 isFilterMenuVisibleOnMouseDown : state . isMarkerFiltersMenuVisible ,
86133 } ) ) ;
87134 } ;
88135
136+ _onMouseDownToggleCopyTableMenu = ( ) => {
137+ this . setState ( ( state ) => ( {
138+ isCopyTableMenuVisibleOnMouseDown : state . isMarkerCopyTableMenuVisible ,
139+ } ) ) ;
140+ } ;
141+
89142 override render ( ) {
90- const { searchString, allowSwitchingStackType } = this . props ;
91- const { isMarkerFiltersMenuVisible } = this . state ;
143+ const { searchString, allowSwitchingStackType, copyTable } = this . props ;
144+ const { isMarkerFiltersMenuVisible, isMarkerCopyTableMenuVisible } =
145+ this . state ;
92146
93147 return (
94148 < div className = "markerSettings" >
@@ -99,6 +153,26 @@ class MarkerSettingsImpl extends PureComponent<Props, State> {
99153 </ li >
100154 ) : null }
101155 </ ul >
156+ { copyTable ? (
157+ < Localized id = "MarkerSettings--copy-table" attrs = { { title : true } } >
158+ < button
159+ className = { classNames (
160+ 'copyTableButton' ,
161+ 'photon-button' ,
162+ 'photon-button-ghost' ,
163+ {
164+ 'photon-button-ghost--checked' : isMarkerCopyTableMenuVisible ,
165+ }
166+ ) }
167+ title = "Copy table as text"
168+ type = "button"
169+ onClick = { this . _onClickToggleCopyTableMenu }
170+ onMouseDown = { this . _onMouseDownToggleCopyTableMenu }
171+ />
172+ </ Localized >
173+ ) : (
174+ ''
175+ ) }
102176 < Localized
103177 id = "MarkerSettings--panel-search"
104178 attrs = { { label : true , title : true } }
@@ -132,12 +206,21 @@ class MarkerSettingsImpl extends PureComponent<Props, State> {
132206 onShow = { this . _onShowFiltersContextMenu }
133207 onHide = { this . _onHideFiltersContextMenu }
134208 />
209+ < MarkerCopyTableContextMenu
210+ onShow = { this . _onShowCopyTableContextMenu }
211+ onHide = { this . _onHideCopyTableContextMenu }
212+ onCopy = { this . _onCopyTable }
213+ />
135214 </ div >
136215 ) ;
137216 }
138217}
139218
140- export const MarkerSettings = explicitConnect < { } , StateProps , DispatchProps > ( {
219+ export const MarkerSettings = explicitConnect <
220+ OwnProps ,
221+ StateProps ,
222+ DispatchProps
223+ > ( {
141224 mapStateToProps : ( state ) => ( {
142225 searchString : getMarkersSearchString ( state ) ,
143226 allowSwitchingStackType : getProfileUsesMultipleStackTypes ( state ) ,
0 commit comments