feat(core): impl ai onboarding templates (#7341)

This commit is contained in:
EYHN
2024-06-26 13:49:23 +00:00
parent aeb666f95e
commit dcf766f0ee
10 changed files with 69 additions and 8 deletions
@@ -213,6 +213,7 @@ export class ChatPanelMessages extends WithDisposable(ShadowlessElement) {
width: '85%', width: '85%',
alignItems: 'center', alignItems: 'center',
justifyContent: 'start', justifyContent: 'start',
cursor: 'pointer',
})} })}
> >
${config.icon} ${config.icon}
@@ -5,31 +5,62 @@ import {
PreloadImageIcon, PreloadImageIcon,
PreloadPenIcon, PreloadPenIcon,
} from '../_common/icons.js'; } from '../_common/icons.js';
import { AIProvider } from '../provider.js';
import completeWritingWithAI from './templates/completeWritingWithAI.zip';
import freelyCommunicateWithAI from './templates/freelyCommunicateWithAI.zip';
import readAforeign from './templates/readAforeign.zip';
import redHat from './templates/redHat.zip';
import TidyMindMapV3 from './templates/TidyMindMapV3.zip';
export const AIPreloadConfig = [ export const AIPreloadConfig = [
{ {
icon: ArticleIcon, icon: ArticleIcon,
text: 'Read a foreign language article with AI', text: 'Read a foreign language article with AI',
handler: () => {}, //waiting for implementation handler: () => {
AIProvider.slots.requestInsertTemplate.emit({
template: readAforeign,
mode: 'edgeless',
});
},
}, },
{ {
icon: MindmapIcon, icon: MindmapIcon,
text: 'Tidy a article with AI MindMap Action', text: 'Tidy a article with AI MindMap Action',
handler: () => {}, handler: () => {
AIProvider.slots.requestInsertTemplate.emit({
template: TidyMindMapV3,
mode: 'edgeless',
});
},
}, },
{ {
icon: PreloadImageIcon, icon: PreloadImageIcon,
text: 'Add illustrations to the article', text: 'Add illustrations to the article',
handler: () => {}, handler: () => {
AIProvider.slots.requestInsertTemplate.emit({
template: redHat,
mode: 'edgeless',
});
},
}, },
{ {
icon: PreloadPenIcon, icon: PreloadPenIcon,
text: 'Complete writing with AI', text: 'Complete writing with AI',
handler: () => {}, handler: () => {
AIProvider.slots.requestInsertTemplate.emit({
template: completeWritingWithAI,
mode: 'edgeless',
});
},
}, },
{ {
icon: CommunicateIcon, icon: CommunicateIcon,
text: 'Freely communicate with AI', text: 'Freely communicate with AI',
handler: () => {}, handler: () => {
AIProvider.slots.requestInsertTemplate.emit({
template: freelyCommunicateWithAI,
mode: 'edgeless',
});
},
}, },
]; ];
@@ -106,6 +106,10 @@ export class AIProvider {
// use case: when user selects "continue in chat" in an ask ai result panel // use case: when user selects "continue in chat" in an ask ai result panel
// do we need to pass the context to the chat panel? // do we need to pass the context to the chat panel?
requestOpenWithChat: new Slot<AIChatParams>(), requestOpenWithChat: new Slot<AIChatParams>(),
requestInsertTemplate: new Slot<{
template: string;
mode: 'page' | 'edgeless';
}>(),
requestLogin: new Slot<{ host: EditorHost }>(), requestLogin: new Slot<{ host: EditorHost }>(),
requestUpgradePlan: new Slot<{ host: EditorHost }>(), requestUpgradePlan: new Slot<{ host: EditorHost }>(),
// when an action is requested to run in edgeless mode (show a toast in affine) // when an action is requested to run in edgeless mode (show a toast in affine)
@@ -1,3 +1,4 @@
import { ZipTransformer } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils'; import { assertExists } from '@blocksuite/global/utils';
import { import {
DndContext, DndContext,
@@ -21,6 +22,7 @@ import { createPortal } from 'react-dom';
import { Map as YMap } from 'yjs'; import { Map as YMap } from 'yjs';
import { openSettingModalAtom } from '../atoms'; import { openSettingModalAtom } from '../atoms';
import { AIProvider } from '../blocksuite/presets/ai';
import { WorkspaceAIOnboarding } from '../components/affine/ai-onboarding'; import { WorkspaceAIOnboarding } from '../components/affine/ai-onboarding';
import { AppContainer } from '../components/affine/app-container'; import { AppContainer } from '../components/affine/app-container';
import { SyncAwareness } from '../components/affine/awareness'; import { SyncAwareness } from '../components/affine/awareness';
@@ -107,6 +109,7 @@ export const WorkspaceLayout = function WorkspaceLayout({
export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => { export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
const currentWorkspace = useService(WorkspaceService).workspace; const currentWorkspace = useService(WorkspaceService).workspace;
const docsList = useService(DocsService).list;
const { openPage } = useNavigateHelper(); const { openPage } = useNavigateHelper();
const pageHelper = usePageHelper(currentWorkspace.docCollection); const pageHelper = usePageHelper(currentWorkspace.docCollection);
@@ -121,6 +124,28 @@ export const WorkspaceLayoutInner = ({ children }: PropsWithChildren) => {
workbench.location$.map(location => basename + location.pathname) workbench.location$.map(location => basename + location.pathname)
); );
useEffect(() => {
const disposable = AIProvider.slots.requestInsertTemplate.on(
({ template, mode }) => {
(async () => {
const templateZip = await fetch(template);
const templateBlob = await templateZip.blob();
const [doc] = await ZipTransformer.importDocs(
currentWorkspace.docCollection,
templateBlob
);
doc.resetHistory();
docsList.setMode(doc.id, mode);
workbench.openPage(doc.id);
})().catch(err => {
console.error(err);
});
}
);
return () => disposable.dispose();
}, [currentWorkspace.docCollection, docsList, workbench]);
useRegisterWorkspaceCommands(); useRegisterWorkspaceCommands();
useRegisterNavigationCommands(); useRegisterNavigationCommands();
useRegisterFindInPageCommands(); useRegisterFindInPageCommands();
@@ -95,14 +95,13 @@ const DetailPageImpl = memo(function DetailPageImpl() {
}, [editor, isActiveView, setActiveBlockSuiteEditor]); }, [editor, isActiveView, setActiveBlockSuiteEditor]);
useEffect(() => { useEffect(() => {
AIProvider.slots.requestOpenWithChat.on(params => { const disposable = AIProvider.slots.requestOpenWithChat.on(params => {
const opened = rightSidebar.isOpen$.value; const opened = rightSidebar.isOpen$.value;
const actived = activeTabName === 'chat'; const actived = activeTabName === 'chat';
if (!opened) { if (!opened) {
rightSidebar.open(); rightSidebar.open();
} }
if (!actived) { if (!actived) {
setActiveTabName('chat'); setActiveTabName('chat');
} }
@@ -122,7 +121,8 @@ const DetailPageImpl = memo(function DetailPageImpl() {
setTabOnLoad(null); setTabOnLoad(null);
} }
}); });
}, [activeTabName, rightSidebar, setActiveTabName, setTabOnLoad]); return disposable.dispose();
}, [activeTabName, rightSidebar, setActiveTabName]);
useEffect(() => { useEffect(() => {
if (isActiveView) { if (isActiveView) {