fix: cmd-k keybinding not show when editor input is active (#7398)

This commit is contained in:
Peng Xiao
2024-07-01 19:31:36 +08:00
committed by GitHub
parent 4d484ea814
commit 8c4a42f0e6
3 changed files with 58 additions and 14 deletions

View File

@@ -30,6 +30,7 @@ export type CommandCategory =
export interface KeybindingOptions { export interface KeybindingOptions {
binding: string; binding: string;
capture?: boolean;
// some keybindings are already registered in blocksuite // some keybindings are already registered in blocksuite
// we can skip the registration of these keybindings __FOR NOW__ // we can skip the registration of these keybindings __FOR NOW__
skipRegister?: boolean; skipRegister?: boolean;

View File

@@ -1,12 +1,50 @@
import { DebugLogger } from '@affine/debug'; import { DebugLogger } from '@affine/debug';
// @ts-expect-error upstream type is wrong // @ts-expect-error upstream type is wrong
import { tinykeys } from 'tinykeys'; import { createKeybindingsHandler } from 'tinykeys';
import type { AffineCommand, AffineCommandOptions } from './command'; import type { AffineCommand, AffineCommandOptions } from './command';
import { createAffineCommand } from './command'; import { createAffineCommand } from './command';
const commandLogger = new DebugLogger('command:registry'); const commandLogger = new DebugLogger('command:registry');
interface KeyBindingMap {
[keybinding: string]: (event: KeyboardEvent) => void;
}
export interface KeyBindingOptions {
/**
* Key presses will listen to this event (default: "keydown").
*/
event?: 'keydown' | 'keyup';
/**
* Whether to capture the event during the capture phase (default: false).
*/
capture?: boolean;
/**
* Keybinding sequences will wait this long between key presses before
* cancelling (default: 1000).
*
* **Note:** Setting this value too low (i.e. `300`) will be too fast for many
* of your users.
*/
timeout?: number;
}
const bindKeys = (
target: Window | HTMLElement,
keyBindingMap: KeyBindingMap,
options: KeyBindingOptions = {}
) => {
const event = options.event ?? 'keydown';
const onKeyEvent = createKeybindingsHandler(keyBindingMap, options);
target.addEventListener(event, onKeyEvent, options.capture);
return () => {
target.removeEventListener(event, onKeyEvent, options.capture);
};
};
export const AffineCommandRegistry = new (class { export const AffineCommandRegistry = new (class {
readonly commands: Map<string, AffineCommand> = new Map(); readonly commands: Map<string, AffineCommand> = new Map();
@@ -25,17 +63,21 @@ export const AffineCommandRegistry = new (class {
!command.keyBinding.skipRegister && !command.keyBinding.skipRegister &&
typeof window !== 'undefined' typeof window !== 'undefined'
) { ) {
const { binding: keybinding } = command.keyBinding; const { binding: keybinding, capture } = command.keyBinding;
unsubKb = tinykeys(window, { unsubKb = bindKeys(
[keybinding]: async (e: Event) => { window,
e.preventDefault(); {
try { [keybinding]: (e: Event) => {
await command.run(); e.preventDefault();
} catch (e) { command.run()?.catch(e => {
console.error(`Failed to invoke keybinding [${keybinding}]`, e); console.error(`Failed to run command [${command.id}]`, e);
} });
},
}, },
}); {
capture,
}
);
} }
commandLogger.debug(`Registered command ${command.id}`); commandLogger.debug(`Registered command ${command.id}`);

View File

@@ -23,9 +23,9 @@ import { useNavigateHelper } from './use-navigate-helper';
function hasLinkPopover(editor: AffineEditorContainer | null) { function hasLinkPopover(editor: AffineEditorContainer | null) {
const textSelection = editor?.host?.std.selection.find('text'); const textSelection = editor?.host?.std.selection.find('text');
if (textSelection && textSelection.from.length > 0) { if (editor && textSelection && textSelection.from.length > 0) {
const linkPopup = document.querySelector('link-popup'); const formatBar = editor.host.querySelector('affine-format-bar-widget');
if (linkPopup) { if (formatBar) {
return true; return true;
} }
} }
@@ -42,6 +42,7 @@ function registerCMDKCommand(
category: 'affine:general', category: 'affine:general',
keyBinding: { keyBinding: {
binding: '$mod+K', binding: '$mod+K',
capture: true,
}, },
label: '', label: '',
icon: '', icon: '',