fix(editor): virtual keyboard closes unexpectedly when backspace is pressed after a block (#13386)
Close [AF-2764](https://linear.app/affine-design/issue/AF-2764/移动端没法删除图片和其他非文本block) #### PR Dependency Tree * **PR #13386** 👈 This tree was auto-generated by [Charcoal](https://github.com/danerwilliams/charcoal) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Improved virtual keyboard handling on mobile devices to prevent unexpected keyboard closure during certain editing actions. * Added new signals for keyboard height and safe area, enhancing UI responsiveness and adaptability to keyboard state. * **Refactor** * Streamlined keyboard toolbar logic for more reliable panel height calculation and smoother panel open/close transitions. * Simplified and modernized the approach to toolbar visibility and input mode restoration. * **Style** * Updated keyboard toolbar and panel styling for better positioning and layout consistency across devices. * **Bug Fixes** * Fixed an issue where the virtual keyboard could be incorrectly reported as visible when a physical keyboard is connected. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -24,6 +24,7 @@ import {
|
|||||||
getPrevContentBlock,
|
getPrevContentBlock,
|
||||||
matchModels,
|
matchModels,
|
||||||
} from '@blocksuite/affine-shared/utils';
|
} from '@blocksuite/affine-shared/utils';
|
||||||
|
import { IS_MOBILE } from '@blocksuite/global/env';
|
||||||
import { BlockSelection, type EditorHost } from '@blocksuite/std';
|
import { BlockSelection, type EditorHost } from '@blocksuite/std';
|
||||||
import type { BlockModel, Text } from '@blocksuite/store';
|
import type { BlockModel, Text } from '@blocksuite/store';
|
||||||
|
|
||||||
@@ -91,10 +92,17 @@ export function mergeWithPrev(editorHost: EditorHost, model: BlockModel) {
|
|||||||
...EMBED_BLOCK_MODEL_LIST,
|
...EMBED_BLOCK_MODEL_LIST,
|
||||||
])
|
])
|
||||||
) {
|
) {
|
||||||
const selection = editorHost.selection.create(BlockSelection, {
|
// due to create a block selection will clear text selection, which lead
|
||||||
blockId: prevBlock.id,
|
// the virtual keyboard to be auto closed on mobile. This behavior breaks
|
||||||
});
|
// the user experience.
|
||||||
editorHost.selection.setGroup('note', [selection]);
|
if (!IS_MOBILE) {
|
||||||
|
const selection = editorHost.selection.create(BlockSelection, {
|
||||||
|
blockId: prevBlock.id,
|
||||||
|
});
|
||||||
|
editorHost.selection.setGroup('note', [selection]);
|
||||||
|
} else {
|
||||||
|
doc.deleteBlock(prevBlock);
|
||||||
|
}
|
||||||
|
|
||||||
if (model.text?.length === 0) {
|
if (model.text?.length === 0) {
|
||||||
doc.deleteBlock(model, {
|
doc.deleteBlock(model, {
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ export class AffineKeyboardToolbar extends SignalWatcher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _renderItems() {
|
private _renderItems() {
|
||||||
if (document.activeElement !== this.rootComponent)
|
if (!this.std.event.active$.value)
|
||||||
return html`<div class="item-container"></div>`;
|
return html`<div class="item-container"></div>`;
|
||||||
|
|
||||||
const goPrevToolbarAction = when(
|
const goPrevToolbarAction = when(
|
||||||
|
|||||||
@@ -61,29 +61,26 @@ export class AffineKeyboardToolbarWidget extends WidgetComponent<RootBlockModel>
|
|||||||
override connectedCallback(): void {
|
override connectedCallback(): void {
|
||||||
super.connectedCallback();
|
super.connectedCallback();
|
||||||
|
|
||||||
const rootComponent = this.block?.rootComponent;
|
this.disposables.add(
|
||||||
if (rootComponent) {
|
effect(() => {
|
||||||
this.disposables.addFromEvent(rootComponent, 'focus', () => {
|
this._show$.value = this.std.event.active$.value;
|
||||||
this._show$.value = true;
|
})
|
||||||
});
|
);
|
||||||
this.disposables.addFromEvent(rootComponent, 'blur', () => {
|
|
||||||
this._show$.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (this.keyboard.fallback) {
|
const rootComponent = this.block?.rootComponent;
|
||||||
this._initialInputMode = rootComponent.inputMode;
|
if (rootComponent && this.keyboard.fallback) {
|
||||||
this.disposables.add(() => {
|
this._initialInputMode = rootComponent.inputMode;
|
||||||
rootComponent.inputMode = this._initialInputMode;
|
this.disposables.add(() => {
|
||||||
});
|
rootComponent.inputMode = this._initialInputMode;
|
||||||
this.disposables.add(
|
});
|
||||||
effect(() => {
|
this.disposables.add(
|
||||||
// recover input mode when keyboard toolbar is hidden
|
effect(() => {
|
||||||
if (!this._show$.value) {
|
// recover input mode when keyboard toolbar is hidden
|
||||||
rootComponent.inputMode = this._initialInputMode;
|
if (!this._show$.value) {
|
||||||
}
|
rootComponent.inputMode = this._initialInputMode;
|
||||||
})
|
}
|
||||||
);
|
})
|
||||||
}
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this._docTitle) {
|
if (this._docTitle) {
|
||||||
|
|||||||
Reference in New Issue
Block a user