Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle key down events in content model only if was not handled by EditFeature #1972

Merged
merged 10 commits into from
Jul 25, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,6 @@ import { getOnDeleteEntityCallback } from '../utils/handleKeyboardEventCommon';
import { getPendingFormat, setPendingFormat } from '../../modelApi/format/pendingFormat';
import { IContentModelEditor } from '../../publicTypes/IContentModelEditor';
import { isNodeOfType, normalizeContentModel } from 'roosterjs-content-model-dom';
import {
getObjectKeys,
isBlockElement,
isCharacterValue,
isModifierKey,
Position,
} from 'roosterjs-editor-dom';
import {
EditorPlugin,
EntityOperationEvent,
Expand All @@ -24,8 +17,16 @@ import {
NodeType,
PluginEvent,
PluginEventType,
PluginKeyDownEvent,
SelectionRangeTypes,
} from 'roosterjs-editor-types';
import {
getObjectKeys,
isBlockElement,
isCharacterValue,
isModifierKey,
Position,
} from 'roosterjs-editor-dom';

// During IME input, KeyDown event will have "Process" as key
const ProcessKey = 'Process';
Expand Down Expand Up @@ -91,7 +92,7 @@ export default class ContentModelEditPlugin implements EditorPlugin {
break;

case PluginEventType.KeyDown:
this.handleKeyDownEvent(this.editor, event.rawEvent);
this.handleKeyDownEvent(this.editor, event);
break;

case PluginEventType.ContentChanged:
Expand All @@ -112,13 +113,14 @@ export default class ContentModelEditPlugin implements EditorPlugin {
}
}

private handleKeyDownEvent(editor: IContentModelEditor, rawEvent: KeyboardEvent) {
private handleKeyDownEvent(editor: IContentModelEditor, event: PluginKeyDownEvent) {
const rawEvent = event.rawEvent;
const which = rawEvent.which;

if (!this.editWithContentModel || rawEvent.defaultPrevented) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can add the check to handledByEditFeature. We can treat handledByEditFeature in the same way with rawEvent.defaultPrevented

// Other plugins already handled this event, so it is most likely content is already changed, we need to clear cached content model
editor.cacheContentModel(null /*model*/);
} else if (!rawEvent.defaultPrevented) {
} else if (!rawEvent.defaultPrevented && !event.handledByEditFeature) {
// TODO: Consider use ContentEditFeature and need to hide other conflict features that are not based on Content Model
switch (which) {
case Keys.BACKSPACE:
Expand Down
6 changes: 5 additions & 1 deletion packages/roosterjs-editor-core/lib/corePlugins/EditPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,9 @@ export default class EditPlugin implements PluginWithState<EditPluginState> {
let hasFunctionKey = false;
let features: GenericContentEditFeature<PluginEvent>[] | null = null;
let ctrlOrMeta = false;
const isKeyDownEvent = event.eventType == PluginEventType.KeyDown;

if (event.eventType == PluginEventType.KeyDown) {
if (isKeyDownEvent) {
const rawEvent = event.rawEvent;
const range = this.editor?.getSelectionRange();

Expand All @@ -86,6 +87,9 @@ export default class EditPlugin implements PluginWithState<EditPluginState> {
feature.shouldHandleEvent(event, this.editor, ctrlOrMeta)
) {
feature.handleEvent(event, this.editor);
if (isKeyDownEvent) {
event.handledByEditFeature = true;
}
break;
}
}
Expand Down
16 changes: 14 additions & 2 deletions packages/roosterjs-editor-types/lib/event/PluginDomEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ export interface PluginScrollEventData {
scrollContainer: HTMLElement;
}

/**
* Data of PluginKeyDownEvent
*/
export interface PluginKeyDownEventData {
/**
* Whether this event is handled by edit feature
*/
handledByEditFeature: boolean;
}

/**
* A base interface of all DOM events
*/
Expand Down Expand Up @@ -79,7 +89,8 @@ export type PluginMouseEvent = PluginMouseDownEvent | PluginMouseUpEvent | Plugi
* This interface represents a PluginEvent wrapping native KeyDown event
*/
export interface PluginKeyDownEvent
JiuqingSong marked this conversation as resolved.
Show resolved Hide resolved
extends PluginDomEventBase<PluginEventType.KeyDown, KeyboardEvent> {}
extends PluginKeyDownEventData,
PluginDomEventBase<PluginEventType.KeyDown, KeyboardEvent> {}

/**
* This interface represents a PluginEvent wrapping native KeyPress event
Expand Down Expand Up @@ -148,7 +159,8 @@ export type CompatiblePluginMouseEvent =
* This interface represents a PluginEvent wrapping native KeyDown event
*/
export interface CompatiblePluginKeyDownEvent
extends PluginDomEventBase<CompatiblePluginEventType.KeyDown, KeyboardEvent> {}
extends PluginKeyDownEventData,
PluginDomEventBase<CompatiblePluginEventType.KeyDown, KeyboardEvent> {}

/**
* This interface represents a PluginEvent wrapping native KeyPress event
Expand Down
1 change: 1 addition & 0 deletions packages/roosterjs-editor-types/lib/event/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export {
PluginScrollEventData,
PluginMouseUpEventData,
PluginContextMenuEventData,
PluginKeyDownEventData,
} from './PluginDomEvent';
export { PluginEvent } from './PluginEvent';
export {
Expand Down