/* eslint-disable */ import { assertExists } from '@blockeditor/global/utils'; import { INLINE_ROOT_ATTR, type InlineRootElement } from '@blockeditor/inline'; import type { BlockElement, EditorHost } from '@blockeditor/lit'; import type { TemplateResult } from 'lit'; import type { InlineRange } from '@blockeditor/inline'; import type { Flavour } from '../../../models.js'; import { AIIcon } from '../../icons/index.js'; import type { AffineTextAttributes, AffineInlineEditor, } from '../../inline/presets/affine-inline-specs.js'; import { toggleAIPopup } from '../../inline/presets/nodes/ai-node/ai-popup/toggle-ai-popup.js'; import { commonActiveWhen } from '../text-format/utils.js'; import { FORMAT_NATIVE_SUPPORT_FLAVOURS } from '../text-format/consts.js'; import { BLOCK_ID_ATTR } from '../../consts.js'; export interface AIPolishConfig { id : string; name : string; icon : TemplateResult<1>; hotkey ?: string; activeWhen : (host : EditorHost) => boolean; action : (host : EditorHost) => void; } function getCombinedFormatFromInlineEditors( inlineEditors: [AffineInlineEditor, InlineRange | null][] ): any[] { const formatArr: AffineInlineEditor[] = []; const targetInlineRanges : InlineRange[] = []; inlineEditors.forEach(([inlineEditor, inlineRange]) => { if (!inlineRange) return; if (inlineRange.length === 0) return; formatArr.push(inlineEditor); targetInlineRanges.push(inlineRange); }); return [formatArr, targetInlineRanges]; } export const aiPolishConfigs : AIPolishConfig[] = [ { id: 'ai', name: 'Ask AI', icon: AIIcon, hotkey: 'Mod-a', activeWhen: host => commonActiveWhen(host, 'ai'), action: host => { let result : AffineInlineEditor[] = []; let targetInlineRanges : InlineRange[] = []; host.std.command .pipe() .withHost() .try(chain => [ chain .getTextSelection() .getSelectedBlocks({ types: ['text'], }) .inline((ctx, next) => { const { currentTextSelection, selectedBlocks } = ctx; // console.log(222, ctx, currentTextSelection, selectedBlocks) assertExists(currentTextSelection); assertExists(selectedBlocks); if (currentTextSelection.isCollapsed()) return; const selectedInlineEditors = selectedBlocks.flatMap(el => { const inlineRoot = el.querySelector< InlineRootElement >(`[${INLINE_ROOT_ATTR}]`); if (inlineRoot && inlineRoot.inlineEditor.getInlineRange()) { return inlineRoot.inlineEditor; } return []; }); const res = getCombinedFormatFromInlineEditors( selectedInlineEditors.map(e => [e, e.getInlineRange()]) ); result = res[0]; targetInlineRanges = res[1]; next(); }), chain .getBlockSelections() .getSelectedBlocks({ types: ['block'], }) .inline((ctx, next) => { const { selectedBlocks } = ctx; assertExists(selectedBlocks); const selectedInlineEditors = selectedBlocks.flatMap(el => { const inlineRoot = el.querySelector< InlineRootElement >(`[${INLINE_ROOT_ATTR}]`); if (inlineRoot) { return inlineRoot.inlineEditor; } return []; }); const res = getCombinedFormatFromInlineEditors( selectedInlineEditors.map(e => [ e, { index: 0, length: e.yTextLength, }, ]) ); result = res[0]; targetInlineRanges = res[1]; next(); }), chain.inline(() => { const selectedInlineEditors = Array.from( host.querySelectorAll(`[${INLINE_ROOT_ATTR}]`) ) .filter(el => { const selection = document.getSelection(); if (!selection || selection.rangeCount === 0) return false; const range = selection.getRangeAt(0); return range.intersectsNode(el); }) .filter(el => { const blockElement = el.closest( `[${BLOCK_ID_ATTR}]` ); if (blockElement) { return FORMAT_NATIVE_SUPPORT_FLAVOURS.includes( blockElement.model.flavour as Flavour ); } return false; }) .map(el => el.inlineEditor); const res = getCombinedFormatFromInlineEditors( selectedInlineEditors.map(e => [e, e.getInlineRange()]) ); result = res[0]; targetInlineRanges = res[1]; }), ]) .run(); toggleAIPopup(result, 'select', targetInlineRanges); }, }, ];