mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 19:26:08 +08:00 
			
		
		
		
	Merge pull request #1861 from TriliumNext/content-menu-target
Make it show which node triggered the event when right-clicking on tree
This commit is contained in:
		
						commit
						43d1b53bca
					
				
					 3 changed files with 27 additions and 26 deletions
				
			
		|  | @ -10,6 +10,7 @@ interface ContextMenuOptions<T> { | ||||||
|     items: MenuItem<T>[]; |     items: MenuItem<T>[]; | ||||||
|     /** On mobile, if set to `true` then the context menu is shown near the element. If `false` (default), then the context menu is shown at the bottom of the screen. */ |     /** On mobile, if set to `true` then the context menu is shown near the element. If `false` (default), then the context menu is shown at the bottom of the screen. */ | ||||||
|     forcePositionOnMobile?: boolean; |     forcePositionOnMobile?: boolean; | ||||||
|  |     onHide?: () => void; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| interface MenuSeparatorItem { | interface MenuSeparatorItem { | ||||||
|  | @ -36,7 +37,6 @@ export type ContextMenuEvent = PointerEvent | MouseEvent | JQuery.ContextMenuEve | ||||||
| class ContextMenu { | class ContextMenu { | ||||||
|     private $widget: JQuery<HTMLElement>; |     private $widget: JQuery<HTMLElement>; | ||||||
|     private $cover: JQuery<HTMLElement>; |     private $cover: JQuery<HTMLElement>; | ||||||
|     private dateContextMenuOpenedMs: number; |  | ||||||
|     private options?: ContextMenuOptions<any>; |     private options?: ContextMenuOptions<any>; | ||||||
|     private isMobile: boolean; |     private isMobile: boolean; | ||||||
| 
 | 
 | ||||||
|  | @ -44,7 +44,6 @@ class ContextMenu { | ||||||
|         this.$widget = $("#context-menu-container"); |         this.$widget = $("#context-menu-container"); | ||||||
|         this.$cover = $("#context-menu-cover"); |         this.$cover = $("#context-menu-cover"); | ||||||
|         this.$widget.addClass("dropend"); |         this.$widget.addClass("dropend"); | ||||||
|         this.dateContextMenuOpenedMs = 0; |  | ||||||
|         this.isMobile = utils.isMobile(); |         this.isMobile = utils.isMobile(); | ||||||
| 
 | 
 | ||||||
|         if (this.isMobile) { |         if (this.isMobile) { | ||||||
|  | @ -76,8 +75,6 @@ class ContextMenu { | ||||||
|         keyboardActionService.updateDisplayedShortcuts(this.$widget); |         keyboardActionService.updateDisplayedShortcuts(this.$widget); | ||||||
| 
 | 
 | ||||||
|         this.positionMenu(); |         this.positionMenu(); | ||||||
| 
 |  | ||||||
|         this.dateContextMenuOpenedMs = Date.now(); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     positionMenu() { |     positionMenu() { | ||||||
|  | @ -186,8 +183,6 @@ class ContextMenu { | ||||||
|                             return false; |                             return false; | ||||||
|                         } |                         } | ||||||
| 
 | 
 | ||||||
|                         this.hide(); |  | ||||||
| 
 |  | ||||||
|                         if ("handler" in item && item.handler) { |                         if ("handler" in item && item.handler) { | ||||||
|                             item.handler(item, e); |                             item.handler(item, e); | ||||||
|                         } |                         } | ||||||
|  | @ -197,6 +192,12 @@ class ContextMenu { | ||||||
|                         // it's important to stop the propagation especially for sub-menus, otherwise the event
 |                         // it's important to stop the propagation especially for sub-menus, otherwise the event
 | ||||||
|                         // might be handled again by top-level menu
 |                         // might be handled again by top-level menu
 | ||||||
|                         return false; |                         return false; | ||||||
|  |                     }) | ||||||
|  |                     .on("mouseup", (e) =>{ | ||||||
|  |                         e.stopPropagation(); | ||||||
|  |                         // Hide the content menu on mouse up to prevent the mouse event from propagating to the elements below.
 | ||||||
|  |                         this.hide(); | ||||||
|  |                         return false; | ||||||
|                     }); |                     }); | ||||||
| 
 | 
 | ||||||
|                 if ("enabled" in item && item.enabled !== undefined && !item.enabled) { |                 if ("enabled" in item && item.enabled !== undefined && !item.enabled) { | ||||||
|  | @ -220,27 +221,14 @@ class ContextMenu { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async hide() { |     async hide() { | ||||||
|         // this date checking comes from change in FF66 - https://github.com/zadam/trilium/issues/468
 |         this.options?.onHide?.(); | ||||||
|         // "contextmenu" event also triggers "click" event which depending on the timing can close the just opened context menu
 |         this.$widget.removeClass("show"); | ||||||
|         // we might filter out right clicks, but then it's better if even right clicks close the context menu
 |         this.$cover.removeClass("show"); | ||||||
|         if (Date.now() - this.dateContextMenuOpenedMs > 300) { |         $("body").removeClass("context-menu-shown"); | ||||||
|             // seems like if we hide the menu immediately, some clicks can get propagated to the underlying component
 |         this.$widget.hide(); | ||||||
|             // see https://github.com/zadam/trilium/pull/3805 for details
 |  | ||||||
|             await timeout(100); |  | ||||||
|             this.$widget.removeClass("show"); |  | ||||||
|             this.$cover.removeClass("show"); |  | ||||||
|             $("body").removeClass("context-menu-shown"); |  | ||||||
|             this.$widget.hide(); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function timeout(ms: number) { |  | ||||||
|     return new Promise((accept, reject) => { |  | ||||||
|         setTimeout(accept, ms); |  | ||||||
|     }); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| const contextMenu = new ContextMenu(); | const contextMenu = new ContextMenu(); | ||||||
| 
 | 
 | ||||||
| export default contextMenu; | export default contextMenu; | ||||||
|  |  | ||||||
|  | @ -19,6 +19,8 @@ interface ConvertToAttachmentResponse { | ||||||
|     attachment?: FAttachment; |     attachment?: FAttachment; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | let lastTargetNode: HTMLElement | null = null; | ||||||
|  | 
 | ||||||
| // This will include all commands that implement ContextMenuCommandData, but it will not work if it additional options are added via the `|` operator,
 | // This will include all commands that implement ContextMenuCommandData, but it will not work if it additional options are added via the `|` operator,
 | ||||||
| // so they need to be added manually.
 | // so they need to be added manually.
 | ||||||
| export type TreeCommandNames = FilteredCommandNames<ContextMenuCommandData> | "openBulkActionsDialog"; | export type TreeCommandNames = FilteredCommandNames<ContextMenuCommandData> | "openBulkActionsDialog"; | ||||||
|  | @ -33,12 +35,19 @@ export default class TreeContextMenu implements SelectMenuItemEventListener<Tree | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async show(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { |     async show(e: PointerEvent | JQuery.TouchStartEvent | JQuery.ContextMenuEvent) { | ||||||
|         contextMenu.show({ |         await contextMenu.show({ | ||||||
|             x: e.pageX ?? 0, |             x: e.pageX ?? 0, | ||||||
|             y: e.pageY ?? 0, |             y: e.pageY ?? 0, | ||||||
|             items: await this.getMenuItems(), |             items: await this.getMenuItems(), | ||||||
|             selectMenuItemHandler: (item, e) => this.selectMenuItemHandler(item) |             selectMenuItemHandler: (item, e) => this.selectMenuItemHandler(item), | ||||||
|  |             onHide: () => { | ||||||
|  |                 lastTargetNode?.classList.remove('fancytree-menu-target'); | ||||||
|  |             } | ||||||
|         }); |         }); | ||||||
|  |         // It's placed after show to ensure the old target is cleared before showing the context menu again on repeated right-clicks.
 | ||||||
|  |         lastTargetNode?.classList.remove('fancytree-menu-target'); | ||||||
|  |         lastTargetNode = this.node.span; | ||||||
|  |         lastTargetNode.classList.add('fancytree-menu-target'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     async getMenuItems(): Promise<MenuItem<TreeCommandNames>[]> { |     async getMenuItems(): Promise<MenuItem<TreeCommandNames>[]> { | ||||||
|  |  | ||||||
|  | @ -208,6 +208,10 @@ span.fancytree-node:hover { | ||||||
|     border: 1px solid var(--main-border-color); |     border: 1px solid var(--main-border-color); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | span.fancytree-node.fancytree-menu-target { | ||||||
|  |     box-shadow: inset 0 0 0 1px var(--main-border-color); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| .fancytree-title:hover, | .fancytree-title:hover, | ||||||
| span.fancytree-node:hover .fancytree-title { | span.fancytree-node:hover .fancytree-title { | ||||||
|     border: 0; |     border: 0; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue