mirror of
https://github.com/toeverything/AFFiNE.git
synced 2024-12-14 12:22:19 +03:00
feat: block slides insert before image load finished (#7948)
This commit is contained in:
parent
5e555b3807
commit
b57388fd85
@ -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<string, (data: any) => boolean> = {
|
||||
createSlides: data => !!data.contents,
|
||||
};
|
||||
export function createInsertResp<T extends keyof BlockSuitePresets.AIActions>(
|
||||
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`<div style=${styleMap({ height: '20px', width: '20px' })}>
|
||||
${LightLoadingIcon}
|
||||
</div>`,
|
||||
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<T extends keyof BlockSuitePresets.AIActions>(
|
||||
@ -555,7 +585,7 @@ export function actionToResponse<T extends keyof BlockSuitePresets.AIActions>(
|
||||
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: '',
|
||||
|
@ -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<EdgelessRootService>('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 ?? '';
|
||||
};
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user