Skip to content

Commit e79bdad

Browse files
authored
Merge pull request #3630 from obsidian-tasks-group/refactor-context-menus
refactor: Remove repetition from menu-handling code
2 parents db83c16 + a7e3402 commit e79bdad

File tree

5 files changed

+20
-17
lines changed

5 files changed

+20
-17
lines changed

src/Renderer/QueryResultsRenderer.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import type { TasksFile } from '../Scripting/TasksFile';
1515
import type { ListItem } from '../Task/ListItem';
1616
import { Task } from '../Task/Task';
1717
import { PostponeMenu } from '../ui/Menus/PostponeMenu';
18+
import { showMenu } from '../ui/Menus/TaskEditingMenu';
1819
import { TaskLineRenderer, type TextRenderer, createAndAppendElement } from './TaskLineRenderer';
1920

2021
export type BacklinksEventHandler = (ev: MouseEvent, task: Task) => Promise<void>;
@@ -554,10 +555,7 @@ export class QueryResultsRenderer {
554555
/** Open a context menu on right-click.
555556
*/
556557
button.addEventListener('contextmenu', async (ev: MouseEvent) => {
557-
ev.preventDefault(); // suppress the default context menu
558-
ev.stopPropagation(); // suppress further event propagation
559-
const menu = new PostponeMenu(button, task);
560-
menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
558+
showMenu(ev, new PostponeMenu(button, task));
561559
});
562560
}
563561

src/Renderer/TaskLineRenderer.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Task } from '../Task/Task';
1010
import { TaskRegularExpressions } from '../Task/TaskRegularExpressions';
1111
import { StatusMenu } from '../ui/Menus/StatusMenu';
1212
import type { AllTaskDateFields } from '../DateTime/DateFieldTypes';
13-
import { defaultTaskSaver } from '../ui/Menus/TaskEditingMenu';
13+
import { defaultTaskSaver, showMenu } from '../ui/Menus/TaskEditingMenu';
1414
import { promptForDate } from '../ui/Menus/DatePicker';
1515
import { splitDateText } from '../DateTime/Postponer';
1616
import { DateMenu } from '../ui/Menus/DateMenu';
@@ -188,10 +188,7 @@ export class TaskLineRenderer {
188188
});
189189

190190
checkbox.addEventListener('contextmenu', (ev: MouseEvent) => {
191-
ev.preventDefault(); // suppress the default click behavior
192-
ev.stopPropagation(); // suppress further event propagation
193-
const menu = new StatusMenu(StatusRegistry.getInstance(), task);
194-
menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
191+
showMenu(ev, new StatusMenu(StatusRegistry.getInstance(), task));
195192
});
196193
checkbox.setAttribute('title', 'Right-click for options');
197194
}
@@ -257,10 +254,7 @@ export class TaskLineRenderer {
257254
});
258255

259256
span.addEventListener('contextmenu', (ev: MouseEvent) => {
260-
ev.preventDefault(); // suppress the default context menu
261-
ev.stopPropagation(); // suppress further event propagation
262-
const menu = new DateMenu(componentDateField, task, defaultTaskSaver);
263-
menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
257+
showMenu(ev, new DateMenu(componentDateField, task, defaultTaskSaver));
264258
});
265259
span.setAttribute(
266260
'title',

src/ui/Menus/PriorityMenu.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,7 @@ import { TaskEditingMenu, type TaskSaver, defaultTaskSaver } from './TaskEditing
77
*
88
* @example
99
* editTaskPencil.addEventListener('contextmenu', (ev: MouseEvent) => {
10-
* const menu = new PriorityMenu(task);
11-
* menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
10+
* showMenu(ev, new PriorityMenu(task));
1211
* });
1312
* editTaskPencil.setAttribute('title', 'Right-click for options');
1413
*/

src/ui/Menus/StatusMenu.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ import { TaskEditingMenu, type TaskSaver, defaultTaskSaver } from './TaskEditing
88
*
99
* @example
1010
* checkbox.addEventListener('contextmenu', (ev: MouseEvent) => {
11-
* const menu = new StatusMenu(StatusRegistry.getInstance(), task);
12-
* menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
11+
* showMenu(ev, new StatusMenu(StatusRegistry.getInstance(), task));
1312
* });
1413
* checkbox.setAttribute('title', 'Right-click for options');
1514
*/

src/ui/Menus/TaskEditingMenu.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,22 @@ export async function defaultTaskSaver(originalTask: Task, newTasks: Task | Task
2222
});
2323
}
2424

25+
/**
26+
* A helper function to ensure that menus behave correctly, not overlapping or being overlapped by other menus.
27+
* @param ev
28+
* @param menu
29+
*/
30+
export function showMenu(ev: MouseEvent, menu: Menu) {
31+
ev.preventDefault(); // suppress the default click behavior
32+
ev.stopPropagation(); // suppress further event propagation
33+
menu.showAtPosition({ x: ev.clientX, y: ev.clientY });
34+
}
35+
2536
/**
2637
* Base class for Menus that offer editing one or more properties of a Task object.
2738
*
39+
* Once created, menus should be passed to {@link showMenu}.
40+
*
2841
* A {@link TaskSaver} function must be supplied, in order for any edits to be saved.
2942
* Derived classes should default to using {@link defaultTaskSaver}, but allow
3043
* alternative implementations to be used in tests.

0 commit comments

Comments
 (0)