@@ -10,7 +10,7 @@ interface ContextMenuAction {
1010type ContextMenuActions = ReadonlyArray < ReadonlyArray < ContextMenuAction > > ;
1111
1212type ContextMenuTarget = {
13- type : TargetType . Commit | TargetType . Ref ;
13+ type : TargetType . Commit | TargetType . Ref | TargetType . CommitDetailsView ;
1414 elem : HTMLElement ;
1515 hash : string ;
1616 index : number ;
@@ -19,6 +19,7 @@ type ContextMenuTarget = {
1919
2020class ContextMenu {
2121 private elem : HTMLElement | null = null ;
22+ private onClose : ( ( ) => void ) | null = null ;
2223 private target : ContextMenuTarget | null = null ;
2324
2425 constructor ( ) {
@@ -27,9 +28,8 @@ class ContextMenu {
2728 document . addEventListener ( 'contextmenu' , listener ) ;
2829 }
2930
30- public show ( actions : ContextMenuActions , checked : boolean , target : ContextMenuTarget | null , event : MouseEvent ) {
31- let viewElem = document . getElementById ( 'view' ) , html = '' , handlers : ( ( ) => void ) [ ] = [ ] , handlerId = 0 ;
32- if ( viewElem === null ) return ;
31+ public show ( actions : ContextMenuActions , checked : boolean , target : ContextMenuTarget | null , event : MouseEvent , frameElem : HTMLElement , blockUserInteractionElem : HTMLElement | null = null , onClose : ( ( ) => void ) | null = null ) {
32+ let html = '' , handlers : ( ( ) => void ) [ ] = [ ] , handlerId = 0 ;
3333 this . close ( ) ;
3434
3535 for ( let i = 0 ; i < actions . length ; i ++ ) {
@@ -53,22 +53,23 @@ class ContextMenu {
5353 menu . className = 'contextMenu' + ( checked ? ' checked' : '' ) ;
5454 menu . style . opacity = '0' ;
5555 menu . innerHTML = html ;
56- viewElem . appendChild ( menu ) ;
57- let bounds = menu . getBoundingClientRect ( ) ;
58- let relativeX = event . pageX + bounds . width < viewElem . clientWidth
56+ frameElem . appendChild ( menu ) ;
57+ const menuBounds = menu . getBoundingClientRect ( ) , frameBounds = frameElem . getBoundingClientRect ( ) ;
58+ const relativeX = event . pageX + menuBounds . width < frameBounds . right
5959 ? - 2 // context menu fits to the right
60- : event . pageX - bounds . width > 0
61- ? 2 - bounds . width // context menu fits to the left
62- : - 2 - ( bounds . width - ( viewElem . clientWidth - event . pageX ) ) ; // Overlap the context menu horizontally with the cursor
63- let relativeY = event . pageY + bounds . height < viewElem . clientHeight
60+ : event . pageX - menuBounds . width > 0
61+ ? 2 - menuBounds . width // context menu fits to the left
62+ : - 2 - ( menuBounds . width - ( frameBounds . width - event . pageX ) ) ; // Overlap the context menu horizontally with the cursor
63+ const relativeY = event . pageY + menuBounds . height < frameBounds . bottom
6464 ? - 2 // context menu fits below
65- : event . pageY - bounds . height > 0
66- ? 2 - bounds . height // context menu fits above
67- : - 2 - ( bounds . height - ( viewElem . clientHeight - event . pageY ) ) ; // Overlap the context menu vertically with the cursor
68- menu . style . left = ( viewElem . scrollLeft + Math . max ( event . pageX + relativeX , 2 ) ) + 'px' ;
69- menu . style . top = ( viewElem . scrollTop + Math . max ( event . pageY + relativeY , 2 ) ) + 'px' ;
65+ : event . pageY - menuBounds . height > 0
66+ ? 2 - menuBounds . height // context menu fits above
67+ : - 2 - ( menuBounds . height - ( frameBounds . height - event . pageY ) ) ; // Overlap the context menu vertically with the cursor
68+ menu . style . left = ( frameElem . scrollLeft + Math . max ( event . pageX - frameBounds . left + relativeX , 2 ) ) + 'px' ;
69+ menu . style . top = ( frameElem . scrollTop + Math . max ( event . pageY - frameBounds . top + relativeY , 2 ) ) + 'px' ;
7070 menu . style . opacity = '1' ;
7171 this . elem = menu ;
72+ this . onClose = onClose ;
7273
7374 addListenerToClass ( 'contextMenuItem' , 'click' , ( e ) => {
7475 e . stopPropagation ( ) ;
@@ -80,15 +81,22 @@ class ContextMenu {
8081 if ( this . target !== null && this . target . type !== TargetType . Repo ) {
8182 alterClass ( this . target . elem , CLASS_CONTEXT_MENU_ACTIVE , true ) ;
8283 }
84+
85+ if ( blockUserInteractionElem !== null ) {
86+ alterClass ( blockUserInteractionElem , CLASS_BLOCK_USER_INTERACTION , true ) ;
87+ }
8388 }
8489
8590 public close ( ) {
8691 if ( this . elem !== null ) {
8792 this . elem . remove ( ) ;
8893 this . elem = null ;
8994 }
90- if ( this . target !== null && this . target . type !== TargetType . Repo ) {
91- alterClass ( this . target . elem , CLASS_CONTEXT_MENU_ACTIVE , false ) ;
95+ alterClassOfCollection ( < HTMLCollectionOf < HTMLElement > > document . getElementsByClassName ( CLASS_BLOCK_USER_INTERACTION ) , CLASS_BLOCK_USER_INTERACTION , false ) ;
96+ alterClassOfCollection ( < HTMLCollectionOf < HTMLElement > > document . getElementsByClassName ( CLASS_CONTEXT_MENU_ACTIVE ) , CLASS_CONTEXT_MENU_ACTIVE , false ) ;
97+ if ( this . onClose !== null ) {
98+ this . onClose ( ) ;
99+ this . onClose = null ;
92100 }
93101 this . target = null ;
94102 }
@@ -106,8 +114,10 @@ class ContextMenu {
106114 if ( commitElem !== null ) {
107115 if ( typeof this . target . ref === 'undefined' ) {
108116 // ContextMenu is only dependent on the commit itself
109- this . target . elem = commitElem ;
110- alterClass ( this . target . elem , CLASS_CONTEXT_MENU_ACTIVE , true ) ;
117+ if ( this . target . type !== TargetType . CommitDetailsView ) {
118+ this . target . elem = commitElem ;
119+ alterClass ( this . target . elem , CLASS_CONTEXT_MENU_ACTIVE , true ) ;
120+ }
111121 return ;
112122 } else {
113123 // ContextMenu is dependent on the commit and ref
0 commit comments