From b57388fd85ba61dd6b270a6e064a33ea489208f8 Mon Sep 17 00:00:00 2001 From: darkskygit Date: Thu, 22 Aug 2024 17:46:06 +0000 Subject: [PATCH] feat: block slides insert before image load finished (#7948) --- .../presets/ai/actions/edgeless-response.ts | 62 ++++++++++---- .../blocksuite/presets/ai/chat-panel/utils.ts | 84 ------------------- .../presets/ai/messages/slides-renderer.ts | 4 + 3 files changed, 50 insertions(+), 100 deletions(-) delete mode 100644 packages/frontend/core/src/blocksuite/presets/ai/chat-panel/utils.ts diff --git a/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts b/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts index 320e79b1c4657..acd880775339e 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/actions/edgeless-response.ts @@ -18,11 +18,13 @@ import { fitContent, ImageBlockModel, InsertBelowIcon, + LightLoadingIcon, NoteDisplayMode, ResetIcon, } from '@blocksuite/blocks'; import { assertExists, Bound } from '@blocksuite/global/utils'; -import type { TemplateResult } from 'lit'; +import { html, type TemplateResult } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; import { AIPenIcon, ChatWithAIIcon } from '../_common/icons'; import { insertFromMarkdown } from '../_common/markdown-utils'; @@ -98,27 +100,55 @@ export function retry(panel: AffineAIPanelWidget): AIItemConfig { }; } +const extraConditions: Record boolean> = { + createSlides: data => !!data.contents, +}; export function createInsertResp( id: T, handler: (host: EditorHost, ctx: CtxRecord) => void, host: EditorHost, ctx: CtxRecord, buttonText: string = 'Insert below' -): AIItemConfig { - return { - name: buttonText, - icon: InsertBelowIcon, - showWhen: () => { - const panel = getAIPanel(host); - return !EXCLUDING_INSERT_ACTIONS.includes(id) && !!panel.answer; +): AIItemConfig[] { + const extraCondition = extraConditions[id] || ((_: any) => true); + return [ + { + name: `${buttonText} - Loading...`, + icon: html`
+ ${LightLoadingIcon} +
`, + showWhen: () => { + const panel = getAIPanel(host); + const data = ctx.get(); + return ( + !EXCLUDING_INSERT_ACTIONS.includes(id) && + !!panel.answer && + // required data for insert + !extraCondition(data) + ); + }, }, - handler: () => { - reportResponse('result:insert'); - handler(host, ctx); - const panel = getAIPanel(host); - panel.hide(); + { + name: buttonText, + icon: InsertBelowIcon, + showWhen: () => { + const panel = getAIPanel(host); + const data = ctx.get(); + return ( + !EXCLUDING_INSERT_ACTIONS.includes(id) && + !!panel.answer && + // required data for insert + !!extraCondition(data) + ); + }, + handler: () => { + reportResponse('result:insert'); + handler(host, ctx); + const panel = getAIPanel(host); + panel.hide(); + }, }, - }; + ]; } export function asCaption( @@ -555,7 +585,7 @@ export function actionToResponse( panel.hide(); }, }, - getInsertAndReplaceHandler(id, host, ctx, variants), + ...getInsertAndReplaceHandler(id, host, ctx, variants), asCaption(id, host), retry(getAIPanel(host)), discard(getAIPanel(host), getEdgelessCopilotWidget(host)), @@ -603,7 +633,7 @@ export function actionToErrorResponse< responses: [ { name: 'Response', - items: [getInsertAndReplaceHandler(id, host, ctx, variants)], + items: getInsertAndReplaceHandler(id, host, ctx, variants), }, { name: '', diff --git a/packages/frontend/core/src/blocksuite/presets/ai/chat-panel/utils.ts b/packages/frontend/core/src/blocksuite/presets/ai/chat-panel/utils.ts deleted file mode 100644 index 9469259e37972..0000000000000 --- a/packages/frontend/core/src/blocksuite/presets/ai/chat-panel/utils.ts +++ /dev/null @@ -1,84 +0,0 @@ -import type { EditorHost } from '@blocksuite/block-std'; -import type { EdgelessRootService } from '@blocksuite/blocks'; -import type { BlockSnapshot } from '@blocksuite/store'; - -import { markdownToSnapshot } from '../_common/markdown-utils'; -import { getSurfaceElementFromEditor } from '../_common/selection-utils'; -import { basicTheme } from '../slides/template'; - -type PPTSection = { - title: string; - content: string; - keywords: string; -}; - -type PPTDoc = { - isCover: boolean; - title: string; - sections: PPTSection[]; -}; - -export const PPTBuilder = (host: EditorHost) => { - const service = host.spec.getService('affine:page'); - const docs: PPTDoc[] = []; - let done = false; - const addDoc = async (block: BlockSnapshot) => { - const sections = block.children.map(v => { - const title = getText(v); - const keywords = getText(v.children[0]); - const content = getText(v.children[1]); - return { - title, - keywords, - content, - } satisfies PPTSection; - }); - const doc: PPTDoc = { - isCover: docs.length === 0, - title: getText(block), - sections, - }; - docs.push(doc); - - if (doc.sections.length !== 3 || doc.isCover) return; - if (done) return; - done = true; - const job = service.createTemplateJob('template'); - const { images, content } = await basicTheme(doc); - - if (images.length) { - await Promise.all( - images.map(({ id, url }) => - fetch(url) - .then(res => res.blob()) - .then(blob => job.job.assets.set(id, blob)) - ) - ); - } - await job.insertTemplate(content); - getSurfaceElementFromEditor(host).refresh(); - }; - - return { - process: async (text: string) => { - const snapshot = await markdownToSnapshot(text, host); - - const block = snapshot.snapshot.content[0]; - for (const child of block.children) { - await addDoc(child); - const { centerX, centerY, zoom } = service.getFitToScreenData(); - service.viewport.setViewport(zoom, [centerX, centerY]); - } - }, - done: async (text: string) => { - const snapshot = await markdownToSnapshot(text, host); - const block = snapshot.snapshot.content[0]; - await addDoc(block.children[block.children.length - 1]); - }, - }; -}; - -const getText = (block: BlockSnapshot) => { - // @ts-expect-error allow - return block.props.text?.delta?.[0]?.insert ?? ''; -}; diff --git a/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts b/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts index 0bc2110c6c9fc..7264b35e43e90 100644 --- a/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts +++ b/packages/frontend/core/src/blocksuite/presets/ai/messages/slides-renderer.ts @@ -85,6 +85,10 @@ export class AISlidesRenderer extends WithDisposable(LitElement) { contents: res.contents, images: res.images, }); + // refresh loading menu item + getAIPanel(this.host) + .shadowRoot?.querySelector('ai-panel-answer') + ?.requestUpdate(); } }) .catch(console.error);