mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-24 09:52:49 +08:00
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - New Features - Press Enter inside a callout splits the paragraph at the cursor into a new focused paragraph. - Clicking an empty callout inserts and focuses a new paragraph; emoji menu behavior unchanged. - New command to convert a callout paragraph to callout/selection flow for Backspace handling. - New native API: ShareableContent.isUsingMicrophone(processId). - Bug Fixes - Backspace inside callout paragraphs now merges or deletes text predictably and selects the callout when appropriate. - Style - Callout layout refined: top-aligned content and adjusted emoji spacing. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
86 lines
2.3 KiB
TypeScript
86 lines
2.3 KiB
TypeScript
import {
|
|
CalloutBlockModel,
|
|
ParagraphBlockModel,
|
|
} from '@blocksuite/affine-model';
|
|
import { focusTextModel } from '@blocksuite/affine-rich-text';
|
|
import { matchModels } from '@blocksuite/affine-shared/utils';
|
|
import type { Command, EditorHost } from '@blocksuite/std';
|
|
|
|
export const splitCalloutCommand: Command<{
|
|
blockId: string;
|
|
inlineIndex: number;
|
|
currentBlockId: string;
|
|
}> = (ctx, next) => {
|
|
const { blockId, inlineIndex, currentBlockId, std } = ctx;
|
|
const host = std.host as EditorHost;
|
|
const doc = host.store;
|
|
|
|
const calloutModel = doc.getBlock(blockId)?.model;
|
|
if (!calloutModel || !matchModels(calloutModel, [CalloutBlockModel])) {
|
|
console.error(`block ${blockId} is not a callout block`);
|
|
return;
|
|
}
|
|
|
|
const currentModel = doc.getBlock(currentBlockId)?.model;
|
|
if (!currentModel) {
|
|
console.error(`current block ${currentBlockId} not found`);
|
|
return;
|
|
}
|
|
|
|
doc.captureSync();
|
|
|
|
if (matchModels(currentModel, [ParagraphBlockModel])) {
|
|
// User is in a paragraph within the callout's children
|
|
const afterText = currentModel.props.text.split(inlineIndex);
|
|
|
|
// Update the current paragraph's text to keep only the part before cursor
|
|
doc.transact(() => {
|
|
currentModel.props.text.delete(
|
|
inlineIndex,
|
|
currentModel.props.text.length - inlineIndex
|
|
);
|
|
});
|
|
|
|
// Create a new paragraph block after the current one
|
|
const parent = doc.getParent(currentModel);
|
|
if (parent) {
|
|
const currentIndex = parent.children.indexOf(currentModel);
|
|
const newParagraphId = doc.addBlock(
|
|
'affine:paragraph',
|
|
{
|
|
text: afterText,
|
|
},
|
|
parent,
|
|
currentIndex + 1
|
|
);
|
|
|
|
if (newParagraphId) {
|
|
host.updateComplete
|
|
.then(() => {
|
|
focusTextModel(std, newParagraphId);
|
|
})
|
|
.catch(console.error);
|
|
}
|
|
}
|
|
} else {
|
|
// If current block is not a paragraph, create a new paragraph in callout
|
|
const newParagraphId = doc.addBlock(
|
|
'affine:paragraph',
|
|
{
|
|
text: new Text(),
|
|
},
|
|
calloutModel
|
|
);
|
|
|
|
if (newParagraphId) {
|
|
host.updateComplete
|
|
.then(() => {
|
|
focusTextModel(std, newParagraphId);
|
|
})
|
|
.catch(console.error);
|
|
}
|
|
}
|
|
|
|
next();
|
|
};
|