diff --git a/blocksuite/affine/block-code/src/code-block.ts b/blocksuite/affine/block-code/src/code-block.ts index 77c464a128..a7a97ac49e 100644 --- a/blocksuite/affine/block-code/src/code-block.ts +++ b/blocksuite/affine/block-code/src/code-block.ts @@ -182,17 +182,17 @@ export class CodeBlockComponent extends CaptionedBlockComponent< // TODO: move to service for better performance this.bindHotKey({ Backspace: ctx => { - const state = ctx.get('keyboardState'); + const event = ctx.get('defaultState').event; const textSelection = selectionManager.find(TextSelection); if (!textSelection) { - state.raw.preventDefault(); + event.preventDefault(); return; } const from = textSelection.from; if (from.index === 0 && from.length === 0) { - state.raw.preventDefault(); + event.preventDefault(); selectionManager.setGroup('note', [ selectionManager.create(BlockSelection, { blockId: this.blockId }), ]); @@ -215,7 +215,7 @@ export class CodeBlockComponent extends CaptionedBlockComponent< index: index, length: 0, }); - state.raw.preventDefault(); + event.preventDefault(); return true; } diff --git a/blocksuite/affine/block-list/src/list-keymap.ts b/blocksuite/affine/block-list/src/list-keymap.ts index 8733b0bfe2..32367780ca 100644 --- a/blocksuite/affine/block-list/src/list-keymap.ts +++ b/blocksuite/affine/block-list/src/list-keymap.ts @@ -105,7 +105,7 @@ export const ListKeymapExtension = KeymapExtension( const isStart = isCollapsed && text.from.index === 0; if (!isStart) return false; - ctx.get('keyboardState').raw.preventDefault(); + ctx.get('defaultState').event.preventDefault(); std.command .chain() .pipe(listToParagraphCommand, { diff --git a/blocksuite/affine/block-paragraph/src/paragraph-keymap.ts b/blocksuite/affine/block-paragraph/src/paragraph-keymap.ts index dbdb6e9f9e..423c37baa2 100644 --- a/blocksuite/affine/block-paragraph/src/paragraph-keymap.ts +++ b/blocksuite/affine/block-paragraph/src/paragraph-keymap.ts @@ -42,7 +42,7 @@ export const ParagraphKeymapExtension = KeymapExtension( const model = store.getBlock(text.from.blockId)?.model; if (!model || !matchModels(model, [ParagraphBlockModel])) return; - const event = ctx.get('keyboardState').raw; + const event = ctx.get('defaultState').event; event.preventDefault(); // When deleting at line start of a paragraph block, diff --git a/blocksuite/affine/block-root/src/keyboard/keyboard-manager.ts b/blocksuite/affine/block-root/src/keyboard/keyboard-manager.ts index 1722882eac..da4a5d1311 100644 --- a/blocksuite/affine/block-root/src/keyboard/keyboard-manager.ts +++ b/blocksuite/affine/block-root/src/keyboard/keyboard-manager.ts @@ -21,7 +21,7 @@ import { toDraftModel } from '@blocksuite/store'; export class PageKeyboardManager { private readonly _handleDelete: UIEventHandler = ctx => { - const event = ctx.get('keyboardState').raw; + const event = ctx.get('defaultState').event; const blockSelections = this._currentSelection.filter(sel => sel.is(BlockSelection) ); diff --git a/blocksuite/framework/block-std/src/event/control/keyboard.ts b/blocksuite/framework/block-std/src/event/control/keyboard.ts index 38d590e98b..d40b649a63 100644 --- a/blocksuite/framework/block-std/src/event/control/keyboard.ts +++ b/blocksuite/framework/block-std/src/event/control/keyboard.ts @@ -1,4 +1,5 @@ -import { IS_MAC } from '@blocksuite/global/env'; +import { IS_ANDROID, IS_MAC } from '@blocksuite/global/env'; +import { DisposableGroup } from '@blocksuite/global/utils'; import { type UIEventHandler, @@ -6,7 +7,7 @@ import { UIEventStateContext, } from '../base.js'; import type { EventOptions, UIEventDispatcher } from '../dispatcher.js'; -import { bindKeymap } from '../keymap.js'; +import { androidBindKeymapPatch, bindKeymap } from '../keymap.js'; import { KeyboardEventState } from '../state/index.js'; import { EventScopeSourceType, EventSourceState } from '../state/source.js'; @@ -72,17 +73,33 @@ export class KeyboardControl { } bindHotkey(keymap: Record, options?: EventOptions) { - return this._dispatcher.add( - 'keyDown', - ctx => { - if (this.composition) { - return false; - } - const binding = bindKeymap(keymap); - return binding(ctx); - }, - options + const disposables = new DisposableGroup(); + if (IS_ANDROID) { + disposables.add( + this._dispatcher.add( + 'beforeInput', + ctx => { + if (this.composition) return false; + const binding = androidBindKeymapPatch(keymap); + return binding(ctx); + }, + options + ) + ); + } + + disposables.add( + this._dispatcher.add( + 'keyDown', + ctx => { + if (this.composition) return false; + const binding = bindKeymap(keymap); + return binding(ctx); + }, + options + ) ); + return () => disposables.dispose(); } listen() { diff --git a/blocksuite/framework/block-std/src/event/keymap.ts b/blocksuite/framework/block-std/src/event/keymap.ts index 82a86ee7d4..e0b6ff84ae 100644 --- a/blocksuite/framework/block-std/src/event/keymap.ts +++ b/blocksuite/framework/block-std/src/event/keymap.ts @@ -1,13 +1,9 @@ +import { IS_MAC } from '@blocksuite/global/env'; import { BlockSuiteError, ErrorCode } from '@blocksuite/global/exceptions'; import { base, keyName } from 'w3c-keyname'; import type { UIEventHandler } from './base.js'; -const mac = - typeof navigator !== 'undefined' - ? /Mac|iP(hone|[oa]d)/.test(navigator.platform) - : false; - function normalizeKeyName(name: string) { const parts = name.split(/-(?!$)/); let result = parts.at(-1); @@ -33,7 +29,7 @@ function normalizeKeyName(name: string) { return; } if (/^mod$/i.test(mod)) { - if (mac) { + if (IS_MAC) { meta = true; } else { ctrl = true; @@ -107,3 +103,25 @@ export function bindKeymap( return false; }; } + +// In Android, the keypress event dose not contain +// the information about what key is pressed. See +// https://stackoverflow.com/a/68188679 +// https://stackoverflow.com/a/66724830 +export function androidBindKeymapPatch( + bindings: Record +): UIEventHandler { + return ctx => { + const event = ctx.get('defaultState').event; + if (!(event instanceof InputEvent)) return; + + if ( + event.inputType === 'deleteContentBackward' && + 'Backspace' in bindings + ) { + return bindings['Backspace'](ctx); + } + + return false; + }; +}