feat(core): ai onboarding for edgeless mode (#6556)

This commit is contained in:
CatsJuice
2024-04-15 07:25:36 +00:00
parent 257e946d5d
commit b93e79c59d
14 changed files with 88362 additions and 55 deletions
@@ -0,0 +1,12 @@
import { cssVar } from '@toeverything/theme';
import { style } from '@vanilla-extract/css';
export const thumb = style({
borderRadius: 'inherit',
borderBottomLeftRadius: 0,
borderBottomRightRadius: 0,
width: '100%',
height: 211,
background: cssVar('backgroundOverlayPanelColor'),
overflow: 'hidden',
});
@@ -1,9 +1,73 @@
import { notify } from '@affine/component';
import { CurrentWorkspaceService } from '@affine/core/modules/workspace';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { AiIcon } from '@blocksuite/icons';
import { Doc, LiveData, useLiveData, useService } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme';
import Lottie from 'lottie-react';
import { useTheme } from 'next-themes';
import { useEffect, useMemo, useRef } from 'react';
import * as styles from './edgeless.dialog.css';
import mouseDark from './lottie/edgeless/mouse-dark.json';
import mouseLight from './lottie/edgeless/mouse-light.json';
import trackPadDark from './lottie/edgeless/trackpad-dark.json';
import trackPadLight from './lottie/edgeless/trackpad-light.json';
import type { BaseAIOnboardingDialogProps } from './type';
export const AIOnboardingEdgeless = ({
onDismiss: _,
}: BaseAIOnboardingDialogProps) => {
return (
<div>{/* TODO: open edgeless in cloud workspace for the first time */}</div>
);
const EdgelessOnboardingAnimation = () => {
const { resolvedTheme } = useTheme();
const isTrackPad = false;
const data = useMemo(() => {
if (isTrackPad) {
return resolvedTheme === 'dark' ? trackPadDark : trackPadLight;
}
return resolvedTheme === 'dark' ? mouseDark : mouseLight;
}, [isTrackPad, resolvedTheme]);
return <Lottie loop autoplay animationData={data} className={styles.thumb} />;
};
// avoid notifying multiple times
const notifyId$ = new LiveData<string | number | null>(null);
export const AIOnboardingEdgeless = ({
onDismiss,
}: BaseAIOnboardingDialogProps) => {
const t = useAFFiNEI18N();
const notifyId = useLiveData(notifyId$);
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
const currentWorkspace = useLiveData(
useService(CurrentWorkspaceService).currentWorkspace$
);
const isCloud = currentWorkspace?.flavour === WorkspaceFlavour.AFFINE_CLOUD;
const doc = useService(Doc);
const mode = useLiveData(doc.mode$);
useEffect(() => {
if (notifyId) return;
if (isCloud && mode === 'edgeless') {
clearTimeout(timeoutRef.current);
timeoutRef.current = setTimeout(() => {
const id = notify(
{
title: t['com.affine.ai-onboarding.edgeless.title'](),
message: t['com.affine.ai-onboarding.edgeless.message'](),
icon: <AiIcon color={cssVar('processingColor')} />,
thumb: <EdgelessOnboardingAnimation />,
alignMessage: 'icon',
onDismiss,
},
{ duration: 1000 * 60 * 10 }
);
notifyId$.next(id);
}, 1000);
}
}, [isCloud, mode, notifyId, onDismiss, t]);
return null;
};
@@ -16,13 +16,10 @@ const useDismiss = (key: AIOnboardingType) => {
return [dismiss, onDismiss] as const;
};
export const AIOnboarding = () => {
export const WorkspaceAIOnboarding = () => {
const [dismissGeneral, onDismissGeneral] = useDismiss(
AIOnboardingType.GENERAL
);
const [dismissEdgeless, onDismissEdgeless] = useDismiss(
AIOnboardingType.EDGELESS
);
const [dismissLocal, onDismissLocal] = useDismiss(AIOnboardingType.LOCAL);
return (
@@ -30,10 +27,22 @@ export const AIOnboarding = () => {
{dismissGeneral ? null : (
<AIOnboardingGeneral onDismiss={onDismissGeneral} />
)}
{dismissEdgeless ? null : (
<AIOnboardingEdgeless onDismiss={onDismissEdgeless} />
)}
{dismissLocal ? null : <AIOnboardingLocal onDismiss={onDismissLocal} />}
</Suspense>
);
};
export const PageAIOnboarding = () => {
const [dismissEdgeless, onDismissEdgeless] = useDismiss(
AIOnboardingType.EDGELESS
);
return (
<Suspense>
{dismissEdgeless ? null : (
<AIOnboardingEdgeless onDismiss={onDismissEdgeless} />
)}
</Suspense>
);
};