import { assertExists } from '@blockeditor/global/utils'; import type { BlockElement } from '@blockeditor/lit'; import { CorrectIcon, InsertIcon, ImproveIcon, ShorterIcon, LongerIcon, } from '../../../../../icons/ai.js'; import { BLOCK_ID_ATTR } from '../../../../../consts.js'; import type { AffineInlineEditor } from '../../../affine-inline-specs.js'; export type AIConfig = { name: string; icon: any; sendText: string | null; showWhen?: (type?: string) => boolean; action?: ({ inlineEditors, targetInlineRanges, content, }: any) => void | Promise; }; export type AIMenuOptions = { name: string; items: AIConfig[]; }; export const menuGroups: AIMenuOptions[] = [ { name: 'Edit or review selection', items: [ { name: 'Improve writing', icon: ImproveIcon, sendText: '请润色原文', // showWhen: (type, status) => { // return true; // } }, { name: 'Make shorter', icon: ShorterIcon, sendText: '请缩写原文', // showWhen: (type, status) => { // return true; // } }, { name: 'Make longer', icon: LongerIcon, sendText: '请扩写原文', // showWhen: (type, status) => { // return true; // } }, ], }, ]; export const nextMenuGroups: AIMenuOptions[] = [ { name: '', items: [ { name: 'Replace selection', icon: CorrectIcon, sendText: null, showWhen: type => { return type === 'select'; }, action: ({ inlineEditors, targetInlineRanges, content }) => { inlineEditors.forEach( (inlineEditor: AffineInlineEditor, index: number) => { if (index === 0) { inlineEditor.insertText(targetInlineRanges[index], content); } else { const totalTextLength = inlineEditor.yTextLength; const inlineTextLength = targetInlineRanges[index].length; if (totalTextLength === inlineTextLength) { const blockElement = inlineEditor.rootElement.closest( `[${BLOCK_ID_ATTR}]` ); assertExists(blockElement); const page = blockElement.host.page; page.deleteBlock(blockElement.model); } else { inlineEditor.deleteText(targetInlineRanges[index]); } } } ); // inlineEditor.setInlineRange({ // index: targetInlineRange.index, // length: content.length // }); }, }, { name: 'Insert below', icon: InsertIcon, sendText: null, showWhen: type => { return type === 'select'; }, action: ({ inlineEditors, content }) => { let targetFlavour = 'affine:paragraph'; const lastIndex: number = inlineEditors.length - 1; const inlineEditor: AffineInlineEditor = inlineEditors[lastIndex]; const blockElement = inlineEditor.rootElement.closest( `[${BLOCK_ID_ATTR}]` ); assertExists(blockElement); const page = blockElement.host.page; const parent = page.getParent(blockElement.model); assertExists(parent); const index = parent.children.indexOf(blockElement.model); const props = { text: new page.Text(content), }; page.addBlock(targetFlavour, props, parent, index + 1); }, }, { name: 'Done', icon: CorrectIcon, sendText: null, showWhen: type => { return type === 'space'; }, action: ({ inlineEditors, targetInlineRanges, content }) => { const lastIndex: number = inlineEditors.length - 1; inlineEditors[lastIndex].insertText( targetInlineRanges[lastIndex], content ); }, }, ], }, ];