66
77import React , { Component } from "react" ;
88import { bindActionCreators } from "redux" ;
9+ import { showMenu } from "devtools-contextmenu" ;
910import { connect } from "react-redux" ;
11+
12+ import { copyToTheClipboard } from "../../utils/clipboard" ;
13+ import { findFunctionText } from "../../utils/function" ;
14+
1015import actions from "../../actions" ;
11- import { getSelectedSource , getSymbols } from "../../selectors" ;
16+ import {
17+ getSelectedSource ,
18+ getSymbols ,
19+ getSelectedLocation
20+ } from "../../selectors" ;
1221
1322import "./Outline.css" ;
1423import PreviewFunction from "../shared/PreviewFunction" ;
@@ -25,7 +34,10 @@ type Props = {
2534 selectLocation : ( { sourceId : string , line : number } ) => void ,
2635 selectedSource : ?SourceRecord ,
2736 onAlphabetizeClick : Function ,
28- alphabetizeOutline : boolean
37+ alphabetizeOutline : boolean ,
38+ getFunctionText : Function ,
39+ flashLineRange : Function ,
40+ selectedLocation : any
2941} ;
3042
3143export class Outline extends Component < Props > {
@@ -39,6 +51,45 @@ export class Outline extends Component<Props> {
3951 selectLocation ( { sourceId : selectedSourceId , line : startLine } ) ;
4052 }
4153
54+ onContextMenu ( event : SyntheticEvent < HTMLElement > , func: SymbolDeclaration) {
55+ event . stopPropagation ( ) ;
56+ event . preventDefault ( ) ;
57+
58+ const {
59+ selectedSource,
60+ getFunctionText,
61+ flashLineRange,
62+ selectedLocation
63+ } = this . props ;
64+
65+ const copyFunctionKey = L10N . getStr ( "copyFunction.accesskey" ) ;
66+ const copyFunctionLabel = L10N . getStr ( "copyFunction.label" ) ;
67+
68+ if ( ! selectedSource ) {
69+ return;
70+ }
71+
72+ const sourceLine = func . location . start . line ;
73+ const functionText = getFunctionText ( sourceLine ) ;
74+
75+ const copyFunctionItem = {
76+ id : "node-menu-copy-function" ,
77+ label : copyFunctionLabel ,
78+ accesskey : copyFunctionKey ,
79+ disabled : ! functionText ,
80+ click : ( ) => {
81+ flashLineRange ( {
82+ start : func . location . start . line ,
83+ end : func . location . end . line ,
84+ sourceId : selectedLocation . sourceId
85+ } ) ;
86+ return copyToTheClipboard ( functionText ) ;
87+ }
88+ } ;
89+ const menuOptions = [ copyFunctionItem ] ;
90+ showMenu ( event , menuOptions ) ;
91+ }
92+
4293 renderPlaceholder() {
4394 const placeholderMessage = this . props . selectedSource
4495 ? L10N . getStr ( "outline.noFunctions" )
@@ -61,6 +112,7 @@ export class Outline extends Component<Props> {
61112 key = { `${ name } :${ location . start . line } :${ location . start . column } ` }
62113 className = "outline-list__element"
63114 onClick = { ( ) => this . selectItem ( location ) }
115+ onContextMenu = { e => this . onContextMenu ( e , func ) }
64116 >
65117 < span className = "outline-list__element-icon" > λ</ span >
66118 < PreviewFunction func = { { name, parameterNames } } />
@@ -162,7 +214,14 @@ export default connect(
162214 const selectedSource = getSelectedSource ( state ) ;
163215 return {
164216 symbols : getSymbols ( state , selectedSource && selectedSource . toJS ( ) ) ,
165- selectedSource
217+ selectedSource,
218+ selectedLocation : getSelectedLocation ( state ) ,
219+ getFunctionText : line =>
220+ findFunctionText (
221+ line ,
222+ selectedSource . toJS ( ) ,
223+ getSymbols ( state , selectedSource . toJS ( ) )
224+ )
166225 } ;
167226 } ,
168227 dispatch => bindActionCreators ( actions , dispatch )
0 commit comments