mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 06:18:45 +08:00
Merge remote-tracking branch 'origin/canary' into beta
This commit is contained in:
@@ -26,6 +26,7 @@ export type FlexWrapperProps = {
|
|||||||
wrap?: boolean;
|
wrap?: boolean;
|
||||||
flexShrink?: CSSProperties['flexShrink'];
|
flexShrink?: CSSProperties['flexShrink'];
|
||||||
flexGrow?: CSSProperties['flexGrow'];
|
flexGrow?: CSSProperties['flexGrow'];
|
||||||
|
gap?: CSSProperties['gap'];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Sometimes we just want to wrap a component with a div to set flex or other styles, but we don't want to create a new component for it.
|
// Sometimes we just want to wrap a component with a div to set flex or other styles, but we don't want to create a new component for it.
|
||||||
@@ -88,6 +89,7 @@ export const FlexWrapper = styled(Wrapper, {
|
|||||||
'flexDirection',
|
'flexDirection',
|
||||||
'flexShrink',
|
'flexShrink',
|
||||||
'flexGrow',
|
'flexGrow',
|
||||||
|
'gap',
|
||||||
].includes(prop as string);
|
].includes(prop as string);
|
||||||
},
|
},
|
||||||
})<FlexWrapperProps>(({
|
})<FlexWrapperProps>(({
|
||||||
@@ -97,6 +99,7 @@ export const FlexWrapper = styled(Wrapper, {
|
|||||||
flexDirection,
|
flexDirection,
|
||||||
flexShrink,
|
flexShrink,
|
||||||
flexGrow,
|
flexGrow,
|
||||||
|
gap,
|
||||||
}) => {
|
}) => {
|
||||||
return {
|
return {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -106,6 +109,7 @@ export const FlexWrapper = styled(Wrapper, {
|
|||||||
flexDirection,
|
flexDirection,
|
||||||
flexShrink,
|
flexShrink,
|
||||||
flexGrow,
|
flexGrow,
|
||||||
|
gap,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -19,3 +19,15 @@ export const thumbContent = style({
|
|||||||
width: 'calc(100% + 4px)',
|
width: 'calc(100% + 4px)',
|
||||||
height: 'calc(100% + 4px)',
|
height: 'calc(100% + 4px)',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const actionButton = style({
|
||||||
|
fontWeight: 500,
|
||||||
|
fontSize: cssVar('fontSm'),
|
||||||
|
lineHeight: '22px',
|
||||||
|
});
|
||||||
|
export const getStartedButtonText = style({
|
||||||
|
color: cssVar('textSecondaryColor'),
|
||||||
|
});
|
||||||
|
export const purchaseButtonText = style({
|
||||||
|
color: cssVar('textPrimaryColor'),
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { notify } from '@affine/component';
|
import { Button, FlexWrapper, notify } from '@affine/component';
|
||||||
import { openSettingModalAtom } from '@affine/core/atoms';
|
import { openSettingModalAtom } from '@affine/core/atoms';
|
||||||
|
import { SubscriptionService } from '@affine/core/modules/cloud';
|
||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { AiIcon } from '@blocksuite/icons';
|
import { AiIcon } from '@blocksuite/icons';
|
||||||
@@ -10,10 +11,10 @@ import {
|
|||||||
WorkspaceService,
|
WorkspaceService,
|
||||||
} from '@toeverything/infra';
|
} from '@toeverything/infra';
|
||||||
import { cssVar } from '@toeverything/theme';
|
import { cssVar } from '@toeverything/theme';
|
||||||
import { useAtomValue } from 'jotai';
|
import { useAtomValue, useSetAtom } from 'jotai';
|
||||||
import Lottie from 'lottie-react';
|
import Lottie from 'lottie-react';
|
||||||
import { useTheme } from 'next-themes';
|
import { useTheme } from 'next-themes';
|
||||||
import { useEffect, useMemo, useRef } from 'react';
|
import { useCallback, useEffect, useMemo, useRef } from 'react';
|
||||||
|
|
||||||
import * as styles from './edgeless.dialog.css';
|
import * as styles from './edgeless.dialog.css';
|
||||||
import mouseTrackDark from './lottie/edgeless/mouse-track-dark.json';
|
import mouseTrackDark from './lottie/edgeless/mouse-track-dark.json';
|
||||||
@@ -47,22 +48,34 @@ const EdgelessOnboardingAnimation = () => {
|
|||||||
export const AIOnboardingEdgeless = ({
|
export const AIOnboardingEdgeless = ({
|
||||||
onDismiss,
|
onDismiss,
|
||||||
}: BaseAIOnboardingDialogProps) => {
|
}: BaseAIOnboardingDialogProps) => {
|
||||||
const { workspaceService, docService } = useServices({
|
const { workspaceService, docService, subscriptionService } = useServices({
|
||||||
WorkspaceService,
|
WorkspaceService,
|
||||||
DocService,
|
DocService,
|
||||||
|
SubscriptionService,
|
||||||
});
|
});
|
||||||
|
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
const notifyId = useLiveData(edgelessNotifyId$);
|
const notifyId = useLiveData(edgelessNotifyId$);
|
||||||
const generalAIOnboardingOpened = useLiveData(showAIOnboardingGeneral$);
|
const generalAIOnboardingOpened = useLiveData(showAIOnboardingGeneral$);
|
||||||
|
const aiSubscription = useLiveData(subscriptionService.subscription.ai$);
|
||||||
const settingModalOpen = useAtomValue(openSettingModalAtom);
|
const settingModalOpen = useAtomValue(openSettingModalAtom);
|
||||||
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
const timeoutRef = useRef<ReturnType<typeof setTimeout>>();
|
||||||
const isCloud =
|
const isCloud =
|
||||||
workspaceService.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
|
workspaceService.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
|
||||||
|
|
||||||
|
const setSettingModal = useSetAtom(openSettingModalAtom);
|
||||||
|
|
||||||
const doc = docService.doc;
|
const doc = docService.doc;
|
||||||
const mode = useLiveData(doc.mode$);
|
const mode = useLiveData(doc.mode$);
|
||||||
|
|
||||||
|
const goToPricingPlans = useCallback(() => {
|
||||||
|
setSettingModal({
|
||||||
|
open: true,
|
||||||
|
activeTab: 'plans',
|
||||||
|
scrollAnchor: 'aiPricingPlan',
|
||||||
|
});
|
||||||
|
}, [setSettingModal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settingModalOpen.open) return;
|
if (settingModalOpen.open) return;
|
||||||
if (generalAIOnboardingOpened) return;
|
if (generalAIOnboardingOpened) return;
|
||||||
@@ -83,13 +96,46 @@ export const AIOnboardingEdgeless = ({
|
|||||||
thumb: <EdgelessOnboardingAnimation />,
|
thumb: <EdgelessOnboardingAnimation />,
|
||||||
alignMessage: 'icon',
|
alignMessage: 'icon',
|
||||||
onDismiss,
|
onDismiss,
|
||||||
|
footer: (
|
||||||
|
<FlexWrapper marginTop={8} justifyContent="flex-end" gap="12px">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
notify.dismiss(id);
|
||||||
|
onDismiss();
|
||||||
|
}}
|
||||||
|
type="plain"
|
||||||
|
className={styles.actionButton}
|
||||||
|
>
|
||||||
|
<span className={styles.getStartedButtonText}>
|
||||||
|
{t['com.affine.ai-onboarding.edgeless.get-started']()}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
{aiSubscription ? null : (
|
||||||
|
<Button
|
||||||
|
className={styles.actionButton}
|
||||||
|
type="plain"
|
||||||
|
onClick={() => {
|
||||||
|
goToPricingPlans();
|
||||||
|
notify.dismiss(id);
|
||||||
|
onDismiss();
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<span className={styles.purchaseButtonText}>
|
||||||
|
{t['com.affine.ai-onboarding.edgeless.purchase']()}
|
||||||
|
</span>
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
|
</FlexWrapper>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
{ duration: 1000 * 60 * 10 }
|
{ duration: 1000 * 60 * 10 }
|
||||||
);
|
);
|
||||||
edgelessNotifyId$.next(id);
|
edgelessNotifyId$.next(id);
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, [
|
}, [
|
||||||
|
aiSubscription,
|
||||||
generalAIOnboardingOpened,
|
generalAIOnboardingOpened,
|
||||||
|
goToPricingPlans,
|
||||||
isCloud,
|
isCloud,
|
||||||
mode,
|
mode,
|
||||||
notifyId,
|
notifyId,
|
||||||
|
|||||||
@@ -229,7 +229,7 @@ export const AIOnboardingGeneral = ({
|
|||||||
a: (
|
a: (
|
||||||
<a
|
<a
|
||||||
className={styles.privacyLink}
|
className={styles.privacyLink}
|
||||||
href="https://ai.affine.pro"
|
href="https://affine.pro/terms"
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -909,7 +909,7 @@
|
|||||||
"com.affine.payment.billing-setting.upgrade": "Upgrade",
|
"com.affine.payment.billing-setting.upgrade": "Upgrade",
|
||||||
"com.affine.payment.billing-setting.view-invoice": "View Invoice",
|
"com.affine.payment.billing-setting.view-invoice": "View Invoice",
|
||||||
"com.affine.payment.billing-setting.year": "year",
|
"com.affine.payment.billing-setting.year": "year",
|
||||||
"com.affine.payment.billing-setting.ai.free-desc": "Yue are current on the <a>Free plan</a>.",
|
"com.affine.payment.billing-setting.ai.free-desc": "You are current on the <a>Free plan</a>.",
|
||||||
"com.affine.payment.billing-setting.ai.purchase": "Purchase",
|
"com.affine.payment.billing-setting.ai.purchase": "Purchase",
|
||||||
"com.affine.payment.blob-limit.description.local": "The maximum file upload size for local workspaces is {{quota}}.",
|
"com.affine.payment.blob-limit.description.local": "The maximum file upload size for local workspaces is {{quota}}.",
|
||||||
"com.affine.payment.blob-limit.description.member": "The maximum file upload size for this joined workspace is {{quota}}. You can contact the owner of this workspace.",
|
"com.affine.payment.blob-limit.description.member": "The maximum file upload size for this joined workspace is {{quota}}. You can contact the owner of this workspace.",
|
||||||
@@ -1306,8 +1306,10 @@
|
|||||||
"com.affine.ai-onboarding.local.message": "Lets you think bigger, create faster, work smarter and save time for every project.",
|
"com.affine.ai-onboarding.local.message": "Lets you think bigger, create faster, work smarter and save time for every project.",
|
||||||
"com.affine.ai-onboarding.local.action-dismiss": "Dismiss",
|
"com.affine.ai-onboarding.local.action-dismiss": "Dismiss",
|
||||||
"com.affine.ai-onboarding.local.action-learn-more": "Learn More",
|
"com.affine.ai-onboarding.local.action-learn-more": "Learn More",
|
||||||
"com.affine.ai-onboarding.edgeless.title": "Meet AFFiNE AI",
|
"com.affine.ai-onboarding.edgeless.title": "Right-clicking to select content AI",
|
||||||
"com.affine.ai-onboarding.edgeless.message": "Lets you think bigger, create faster, work smarter and save time for every project.",
|
"com.affine.ai-onboarding.edgeless.message": "Lets you think bigger, create faster, work smarter and save time for every project.",
|
||||||
|
"com.affine.ai-onboarding.edgeless.get-started": "Get Started",
|
||||||
|
"com.affine.ai-onboarding.edgeless.purchase": "Upgrade to Unlimited Usage",
|
||||||
"com.affine.ai.login-required.dialog-title": "Sign in to Continue",
|
"com.affine.ai.login-required.dialog-title": "Sign in to Continue",
|
||||||
"com.affine.ai.login-required.dialog-content": "To use AFFiNE AI, please sign in to your AFFiNE Cloud account.",
|
"com.affine.ai.login-required.dialog-content": "To use AFFiNE AI, please sign in to your AFFiNE Cloud account.",
|
||||||
"com.affine.ai.login-required.dialog-confirm": "Sign in",
|
"com.affine.ai.login-required.dialog-confirm": "Sign in",
|
||||||
|
|||||||
Reference in New Issue
Block a user