fix(core): cannot input space at the beginning of a blank paragraph (#12166)

### TL:DR

fix: cannot input space at the beginning of a blank paragraph

> CLOSE BS-3427

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Improved space key handling in the editor: pressing space on an empty AI input now hides the AI panel and inserts a space character back into the editor.

- **Bug Fixes**
  - Prevented the AI panel from processing empty input when space is pressed, ensuring smoother user experience.

- **Tests**
  - Added an end-to-end test verifying that pressing space on an empty AI input hides the AI panel and inserts a space.

- **Refactor**
  - Streamlined event handling logic for space key detection in the editor.

- **Chores**
  - Enhanced editor content retrieval to optionally preserve whitespace while removing invisible characters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
yoyoyohamapi
2025-05-07 07:46:13 +00:00
parent 267bb3a975
commit 8ea39d5438
3 changed files with 63 additions and 9 deletions

View File

@@ -1,9 +1,34 @@
import { TextSelection } from '@blocksuite/affine/std';
import type { RichText } from '@blocksuite/affine/rich-text';
import { type EditorHost, TextSelection } from '@blocksuite/affine/std';
import { handleInlineAskAIAction } from '../../actions/doc-handler';
import { AIProvider } from '../../provider';
import type { AffineAIPanelWidget } from '../../widgets/ai-panel/ai-panel';
function isSpaceEvent(event: KeyboardEvent) {
return event.key === ' ' && event.which === 32 && !event.isComposing;
}
function insertSpace(host: EditorHost) {
const textSelection = host.selection.find(TextSelection);
if (!textSelection || !textSelection.isCollapsed()) return;
const blockComponent = host.view.getBlock(textSelection.from.blockId);
if (!blockComponent) return;
const richText = blockComponent.querySelector('rich-text') as RichText | null;
if (!richText) return;
const inlineEditor = richText.inlineEditor;
inlineEditor?.insertText(
{
index: textSelection.from.index,
length: 0,
},
' '
);
}
export function setupSpaceAIEntry(panel: AffineAIPanelWidget) {
// Background: The keydown event triggered by a space may originate from:
// 1. Normal space insertion
@@ -18,12 +43,19 @@ export function setupSpaceAIEntry(panel: AffineAIPanelWidget) {
const host = panel.host;
const keyboardState = ctx.get('keyboardState');
const event = keyboardState.raw;
if (
AIProvider.actions.chat &&
event.key === ' ' &&
event.which === 32 &&
!event.isComposing
) {
if (AIProvider.actions.chat && isSpaceEvent(event)) {
// If the AI panel is in the input state and the input content is empty,
// insert a space back into the editor.
if (panel.state === 'input') {
const input = panel.shadowRoot?.querySelector('ai-panel-input');
if (input?.textarea.value.trim() === '') {
event.preventDefault();
insertSpace(host);
panel.hide();
return;
}
}
const selection = host.selection.find(TextSelection);
if (selection && selection.isCollapsed() && selection.from.index === 0) {
const block = host.view.getBlock(selection.blockId);