refactor: improve block modularity on server (#758)

This commit is contained in:
Jeremy 2025-02-04 17:15:39 +03:00 committed by GitHub
parent 711da0b94b
commit 9c4dbc8aaa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 419 additions and 259 deletions

76
blocks/image/client.tsx Normal file
View file

@ -0,0 +1,76 @@
import { Block } from '@/components/create-block';
import { CopyIcon, RedoIcon, UndoIcon } from '@/components/icons';
import { ImageEditor } from '@/components/image-editor';
import { toast } from 'sonner';
export const imageBlock = new Block({
kind: 'image',
description: 'Useful for image generation',
onStreamPart: ({ streamPart, setBlock }) => {
if (streamPart.type === 'image-delta') {
setBlock((draftBlock) => ({
...draftBlock,
content: streamPart.content as string,
isVisible: true,
status: 'streaming',
}));
}
},
content: ImageEditor,
actions: [
{
icon: <UndoIcon size={18} />,
description: 'View Previous version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('prev');
},
isDisabled: ({ currentVersionIndex }) => {
if (currentVersionIndex === 0) {
return true;
}
return false;
},
},
{
icon: <RedoIcon size={18} />,
description: 'View Next version',
onClick: ({ handleVersionChange }) => {
handleVersionChange('next');
},
isDisabled: ({ isCurrentVersion }) => {
if (isCurrentVersion) {
return true;
}
return false;
},
},
{
icon: <CopyIcon size={18} />,
description: 'Copy image to clipboard',
onClick: ({ content }) => {
const img = new Image();
img.src = `data:image/png;base64,${content}`;
img.onload = () => {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx?.drawImage(img, 0, 0);
canvas.toBlob((blob) => {
if (blob) {
navigator.clipboard.write([
new ClipboardItem({ 'image/png': blob }),
]);
}
}, 'image/png');
};
toast.success('Copied image to clipboard!');
},
},
],
toolbar: [],
});

54
blocks/image/server.ts Normal file
View file

@ -0,0 +1,54 @@
import { myProvider } from '@/lib/ai/models';
import { createDocumentHandler } from '@/lib/blocks/server';
import { saveDocument } from '@/lib/db/queries';
import { experimental_generateImage } from 'ai';
export const imageDocumentHandler = createDocumentHandler<'image'>({
kind: 'image',
onCreateDocument: async ({ id, title, dataStream, session }) => {
let draftContent = '';
const { image } = await experimental_generateImage({
model: myProvider.imageModel('small-model'),
prompt: title,
n: 1,
});
draftContent = image.base64;
dataStream.writeData({
type: 'image-delta',
content: image.base64,
});
if (session?.user?.id) {
await saveDocument({
id,
title,
kind: 'image',
content: draftContent,
userId: session.user.id,
});
}
return draftContent;
},
onUpdateDocument: async ({ description, dataStream }) => {
let draftContent = '';
const { image } = await experimental_generateImage({
model: myProvider.imageModel('image-model'),
prompt: description,
n: 1,
});
draftContent = image.base64;
dataStream.writeData({
type: 'image-delta',
content: image.base64,
});
return draftContent;
},
});