feat!: Add context menu options for workspace comments (#8035)

* feat: add context menu support and migrate easy options

* feat: pass events to context menu options

* chore: migrate final comment context menu option

* feat: add exports for comment context menu items

* chore: PR comments
This commit is contained in:
Beka Westberg
2024-04-17 20:02:53 +00:00
committed by GitHub
parent 70f3f52911
commit e21bb99ff1
9 changed files with 154 additions and 162 deletions

View File

@@ -9,7 +9,6 @@
import type {Block} from './block.js';
import type {BlockSvg} from './block_svg.js';
import * as browserEvents from './browser_events.js';
import * as clipboard from './clipboard.js';
import {config} from './config.js';
import * as dom from './utils/dom.js';
import type {
@@ -19,15 +18,11 @@ import type {
import * as eventUtils from './events/utils.js';
import {Menu} from './menu.js';
import {MenuItem} from './menuitem.js';
import {Msg} from './msg.js';
import * as aria from './utils/aria.js';
import {Coordinate} from './utils/coordinate.js';
import {Rect} from './utils/rect.js';
import * as serializationBlocks from './serialization/blocks.js';
import * as svgMath from './utils/svg_math.js';
import * as WidgetDiv from './widgetdiv.js';
import {WorkspaceCommentSvg} from './workspace_comment_svg.js';
import type {WorkspaceSvg} from './workspace_svg.js';
import * as Xml from './xml.js';
import * as common from './common.js';
@@ -69,7 +64,7 @@ let menu_: Menu | null = null;
* @param rtl True if RTL, false if LTR.
*/
export function show(
e: Event,
e: PointerEvent,
options: (ContextMenuOption | LegacyContextMenuOption)[],
rtl: boolean,
) {
@@ -78,7 +73,7 @@ export function show(
hide();
return;
}
const menu = populate_(options, rtl);
const menu = populate_(options, rtl, e);
menu_ = menu;
position_(menu, e, rtl);
@@ -95,11 +90,13 @@ export function show(
*
* @param options Array of menu options.
* @param rtl True if RTL, false if LTR.
* @param e The event that triggered the context menu to open.
* @returns The menu that will be shown on right click.
*/
function populate_(
options: (ContextMenuOption | LegacyContextMenuOption)[],
rtl: boolean,
e: PointerEvent,
): Menu {
/* Here's what one option object looks like:
{text: 'Make It So',
@@ -124,7 +121,7 @@ function populate_(
// will not be expecting a scope parameter, so there should be
// no problems. Just assume it is a ContextMenuOption and we'll
// pass undefined if it's not.
option.callback((option as ContextMenuOption).scope);
option.callback((option as ContextMenuOption).scope, e);
}, 0);
});
};
@@ -266,125 +263,3 @@ export function callbackFactory(
return newBlock;
};
}
// Helper functions for creating context menu options.
/**
* Make a context menu option for deleting the current workspace comment.
*
* @param comment The workspace comment where the
* right-click originated.
* @returns A menu option,
* containing text, enabled, and a callback.
* @internal
*/
export function commentDeleteOption(
comment: WorkspaceCommentSvg,
): LegacyContextMenuOption {
const deleteOption = {
text: Msg['REMOVE_COMMENT'],
enabled: true,
callback: function () {
eventUtils.setGroup(true);
comment.dispose();
eventUtils.setGroup(false);
},
};
return deleteOption;
}
/**
* Make a context menu option for duplicating the current workspace comment.
*
* @param comment The workspace comment where the
* right-click originated.
* @returns A menu option,
* containing text, enabled, and a callback.
* @internal
*/
export function commentDuplicateOption(
comment: WorkspaceCommentSvg,
): LegacyContextMenuOption {
const duplicateOption = {
text: Msg['DUPLICATE_COMMENT'],
enabled: true,
callback: function () {
const data = comment.toCopyData();
if (!data) return;
clipboard.paste(data, comment.workspace);
},
};
return duplicateOption;
}
/**
* Make a context menu option for adding a comment on the workspace.
*
* @param ws The workspace where the right-click
* originated.
* @param e The right-click mouse event.
* @returns A menu option, containing text, enabled, and a callback.
* comments are not bundled in.
* @internal
*/
export function workspaceCommentOption(
ws: WorkspaceSvg,
e: Event,
): ContextMenuOption {
/**
* Helper function to create and position a comment correctly based on the
* location of the mouse event.
*/
function addWsComment() {
const comment = new WorkspaceCommentSvg(
ws,
Msg['WORKSPACE_COMMENT_DEFAULT_TEXT'],
WorkspaceCommentSvg.DEFAULT_SIZE,
WorkspaceCommentSvg.DEFAULT_SIZE,
);
const injectionDiv = ws.getInjectionDiv();
// Bounding rect coordinates are in client coordinates, meaning that they
// are in pixels relative to the upper left corner of the visible browser
// window. These coordinates change when you scroll the browser window.
const boundingRect = injectionDiv.getBoundingClientRect();
// The client coordinates offset by the injection div's upper left corner.
const mouseEvent = e as MouseEvent;
const clientOffsetPixels = new Coordinate(
mouseEvent.clientX - boundingRect.left,
mouseEvent.clientY - boundingRect.top,
);
// The offset in pixels between the main workspace's origin and the upper
// left corner of the injection div.
const mainOffsetPixels = ws.getOriginOffsetInPixels();
// The position of the new comment in pixels relative to the origin of the
// main workspace.
const finalOffset = Coordinate.difference(
clientOffsetPixels,
mainOffsetPixels,
);
// The position of the new comment in main workspace coordinates.
finalOffset.scale(1 / ws.scale);
const commentX = finalOffset.x;
const commentY = finalOffset.y;
comment.moveBy(commentX, commentY);
if (ws.rendered) {
comment.initSvg();
comment.render();
common.setSelected(comment);
}
}
const wsCommentOption = {
enabled: true,
} as ContextMenuOption;
wsCommentOption.text = Msg['ADD_COMMENT'];
wsCommentOption.callback = function () {
addWsComment();
};
return wsCommentOption;
}