diff --git a/blocksuite/affine/blocks/embed/src/common/render-linked-doc.ts b/blocksuite/affine/blocks/embed/src/common/render-linked-doc.ts
index 3601db8c52..6a2acdd8af 100644
--- a/blocksuite/affine/blocks/embed/src/common/render-linked-doc.ts
+++ b/blocksuite/affine/blocks/embed/src/common/render-linked-doc.ts
@@ -364,13 +364,16 @@ export function notifyDocCreated(std: BlockStdScope, doc: Store) {
message: 'You can click undo to recovery block content',
accent: 'info',
duration: 10 * 1000,
- action: {
- label: 'Undo',
- onClick: () => {
- doc.undo();
- clear();
+ actions: [
+ {
+ key: 'undo',
+ label: 'Undo',
+ onClick: () => {
+ doc.undo();
+ clear();
+ },
},
- },
+ ],
abort: abortController.signal,
onClose: clear,
});
diff --git a/blocksuite/affine/blocks/note/src/components/view-in-page-notify.css.ts b/blocksuite/affine/blocks/note/src/components/view-in-page-notify.css.ts
deleted file mode 100644
index 409eefeac2..0000000000
--- a/blocksuite/affine/blocks/note/src/components/view-in-page-notify.css.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import { cssVar } from '@toeverything/theme';
-import { cssVarV2 } from '@toeverything/theme/v2';
-import { style } from '@vanilla-extract/css';
-
-export const viewInPageNotifyFooter = style({
- display: 'flex',
- justifyContent: 'flex-end',
- gap: '12px',
-});
-
-export const viewInPageNotifyFooterButton = style({
- padding: '0px 6px',
- borderRadius: '4px',
- color: cssVarV2('text/primary'),
-
- fontSize: cssVar('fontSm'),
- lineHeight: '22px',
- fontWeight: '500',
- textAlign: 'center',
-
- ':hover': {
- background: cssVarV2('layer/background/hoverOverlay'),
- },
-});
diff --git a/blocksuite/affine/blocks/note/src/configs/toolbar.ts b/blocksuite/affine/blocks/note/src/configs/toolbar.ts
index dc13d2cefa..d8a0efbcf9 100644
--- a/blocksuite/affine/blocks/note/src/configs/toolbar.ts
+++ b/blocksuite/affine/blocks/note/src/configs/toolbar.ts
@@ -41,7 +41,6 @@ import { html } from 'lit';
import { keyed } from 'lit/directives/keyed.js';
import { changeNoteDisplayMode } from '../commands';
-import * as styles from '../components/view-in-page-notify.css';
import { NoteConfigExtension } from '../config';
const trackBaseProps = {
@@ -550,22 +549,18 @@ function setDisplayMode(
message: `${data.message} Find it in the TOC for quick navigation.`,
accent: 'success',
duration: 5 * 1000,
- footer: html`
`,
+ actions: [
+ {
+ key: 'undo-display-in-page',
+ label: 'Undo',
+ onClick: () => undo(),
+ },
+ {
+ key: 'view-in-toc',
+ label: 'View in Toc',
+ onClick: () => viewInToc(),
+ },
+ ],
abort: abortController.signal,
onClose: () => {
clear();
diff --git a/blocksuite/affine/components/src/notification/linked-doc.ts b/blocksuite/affine/components/src/notification/linked-doc.ts
index 3d72fb0dbf..fc74b9a18c 100644
--- a/blocksuite/affine/components/src/notification/linked-doc.ts
+++ b/blocksuite/affine/components/src/notification/linked-doc.ts
@@ -35,13 +35,16 @@ function notify(std: BlockStdScope, title: string, message: string) {
message,
accent: 'info',
duration: 10 * 1000,
- action: {
- label: 'Undo',
- onClick: () => {
- doc.undo();
- clear();
+ actions: [
+ {
+ key: 'undo',
+ label: 'Undo',
+ onClick: () => {
+ doc.undo();
+ clear();
+ },
},
- },
+ ],
abort: abortController.signal,
onClose: clear,
});
diff --git a/blocksuite/affine/shared/src/services/notification-service.ts b/blocksuite/affine/shared/src/services/notification-service.ts
index 5ac1c8bcb0..9b8dc2fabb 100644
--- a/blocksuite/affine/shared/src/services/notification-service.ts
+++ b/blocksuite/affine/shared/src/services/notification-service.ts
@@ -29,14 +29,14 @@ export interface NotificationService {
notify(options: {
title: string | TemplateResult;
message?: string | TemplateResult;
- footer?: string | TemplateResult;
accent?: 'info' | 'success' | 'warning' | 'error';
duration?: number; // unit ms, give 0 to disable auto dismiss
abort?: AbortSignal;
- action?: {
+ actions?: {
+ key: string;
label: string | TemplateResult;
onClick: () => void;
- };
+ }[];
onClose: () => void;
}): void;
}
diff --git a/packages/frontend/component/src/ui/notification/desktop/notification-card.tsx b/packages/frontend/component/src/ui/notification/desktop/notification-card.tsx
index 2ab268dd54..f44888a7d1 100644
--- a/packages/frontend/component/src/ui/notification/desktop/notification-card.tsx
+++ b/packages/frontend/component/src/ui/notification/desktop/notification-card.tsx
@@ -4,7 +4,8 @@ import clsx from 'clsx';
import { useCallback } from 'react';
import { Button, IconButton } from '../../button';
-import type { NotificationCardProps } from '../types';
+import { FlexWrapper } from '../../layout/wrapper';
+import type { NotificationActionProps, NotificationCardProps } from '../types';
import { getCardVars } from '../utils';
import * as styles from './styles.css';
@@ -18,10 +19,9 @@ export const DesktopNotificationCard = ({
icon = ,
iconColor,
thumb,
- action,
+ actions,
error,
title,
- footer,
alignMessage = 'title',
onDismiss,
rootAttrs,
@@ -33,13 +33,6 @@ export const DesktopNotificationCard = ({
? t[errorI18nKey](error?.data)
: undefined;
- const onActionClicked = useCallback(() => {
- action?.onClick()?.catch(console.error);
- if (action?.autoClose !== false) {
- onDismiss?.();
- }
- }, [action, onDismiss]);
-
return (
) : null}
{title || errorTitle}
-
- {action ? (
-
-
-
- ) : null}
{notification.message}
-
+
);
};
+
+const NotificationCardAction = ({
+ action,
+ onDismiss,
+}: NotificationActionProps) => {
+ const onActionClicked = useCallback(() => {
+ action.onClick()?.catch(console.error);
+ if (action.autoClose !== false) {
+ onDismiss?.();
+ }
+ }, [action, onDismiss]);
+
+ return (
+
+ );
+};
diff --git a/packages/frontend/component/src/ui/notification/desktop/styles.css.ts b/packages/frontend/component/src/ui/notification/desktop/styles.css.ts
index 05c39a69de..bc0f278ab4 100644
--- a/packages/frontend/component/src/ui/notification/desktop/styles.css.ts
+++ b/packages/frontend/component/src/ui/notification/desktop/styles.css.ts
@@ -55,14 +55,14 @@ export const title = style({
fontSize: 15,
marginRight: 10,
});
-export const action = style({
- marginRight: 16,
-});
+
export const actionButton = style({
color: actionTextColor,
position: 'relative',
background: 'transparent',
border: 'none',
+ fontSize: cssVar('fontSm'),
+ lineHeight: '22px',
});
export const closeButton = style({
selectors: {
diff --git a/packages/frontend/component/src/ui/notification/mobile/notification-card.tsx b/packages/frontend/component/src/ui/notification/mobile/notification-card.tsx
index d520ad4c69..f3efe0b9f8 100644
--- a/packages/frontend/component/src/ui/notification/mobile/notification-card.tsx
+++ b/packages/frontend/component/src/ui/notification/mobile/notification-card.tsx
@@ -4,7 +4,7 @@ import { useCallback, useState } from 'react';
import { Button, IconButton } from '../../button';
import { Modal } from '../../modal';
-import type { NotificationCardProps } from '../types';
+import type { NotificationActionProps, NotificationCardProps } from '../types';
import { getCardVars } from '../utils';
import * as styles from './styles.css';
@@ -70,8 +70,7 @@ const MobileNotifyDetail = ({
iconColor,
title,
message,
- footer,
- action,
+ actions,
error,
} = notification;
const t = useI18n();
@@ -87,12 +86,6 @@ const MobileNotifyDetail = ({
},
[onClose]
);
- const onActionClicked = useCallback(() => {
- action?.onClick()?.catch(console.error);
- if (action?.autoClose !== false) {
- onClose?.();
- }
- }, [action, onClose]);
return (
{message}
{/* actions */}
- {action ? (
-
- ) : null}
- {footer}
+ {actions?.map(action => (
+
+ ))}
);
};
+
+const NotificationCardAction = ({
+ action,
+ onDismiss,
+}: NotificationActionProps) => {
+ const onActionClicked = useCallback(() => {
+ action.onClick()?.catch(console.error);
+ if (action.autoClose !== false) {
+ onDismiss?.();
+ }
+ }, [action, onDismiss]);
+
+ return (
+
+ );
+};
diff --git a/packages/frontend/component/src/ui/notification/notification-center.stories.tsx b/packages/frontend/component/src/ui/notification/notification-center.stories.tsx
index 685e8940e8..2d04f406c1 100644
--- a/packages/frontend/component/src/ui/notification/notification-center.stories.tsx
+++ b/packages/frontend/component/src/ui/notification/notification-center.stories.tsx
@@ -181,10 +181,13 @@ export const WithAction: StoryFn = () => {
),
style,
theme,
- action: {
- label: 'UNDO',
- onClick: () => console.log('undo'),
- },
+ actions: [
+ {
+ key: 'undo',
+ label: 'UNDO',
+ onClick: () => console.log('undo'),
+ },
+ ],
})
}
>
@@ -204,11 +207,14 @@ export const WithAction: StoryFn = () => {
{
title: 'Disable auto close',
message: 'Test with disable auto close',
- action: {
- label: 'UNDO',
- onClick: () => console.log('undo'),
- autoClose: false,
- },
+ actions: [
+ {
+ key: 'undo',
+ label: 'UNDO',
+ onClick: () => console.log('undo'),
+ autoClose: false,
+ },
+ ],
},
{ duration: 22222222 }
);
@@ -296,25 +302,12 @@ export const DifferentSize: StoryFn = () => {
{ duration: 60000 }
);
};
- const openWithFooter = () => {
- notify(
- {
- title: 'With footer',
- message: 'With basic title and one line message',
- footer: (
-
- ),
- },
- { duration: 60000 }
- );
- };
return (
-
);
};
diff --git a/packages/frontend/component/src/ui/notification/types.ts b/packages/frontend/component/src/ui/notification/types.ts
index eced811437..828a03b5f3 100644
--- a/packages/frontend/component/src/ui/notification/types.ts
+++ b/packages/frontend/component/src/ui/notification/types.ts
@@ -14,7 +14,8 @@ export interface Notification {
background?: string;
foreground?: string;
alignMessage?: 'title' | 'icon';
- action?: {
+ actions?: {
+ key: string;
label: ReactNode;
onClick: (() => void) | (() => Promise);
buttonProps?: ButtonProps;
@@ -22,7 +23,7 @@ export interface Notification {
* @default true
*/
autoClose?: boolean;
- };
+ }[];
rootAttrs?: HTMLAttributes;
@@ -33,7 +34,6 @@ export interface Notification {
error?: UserFriendlyError;
icon?: ReactNode;
iconColor?: string;
- footer?: ReactNode;
// events
onDismiss?: () => void;
@@ -50,3 +50,8 @@ export interface NotificationCustomRendererProps {
export interface NotificationCardProps extends HTMLAttributes {
notification: Notification;
}
+
+export interface NotificationActionProps {
+ action: NonNullable[number];
+ onDismiss: Notification['onDismiss'];
+}
diff --git a/packages/frontend/core/src/blocksuite/extensions/editor-config/toolbar/copy-as-image.ts b/packages/frontend/core/src/blocksuite/extensions/editor-config/toolbar/copy-as-image.ts
index e192d8768d..8c74276f9d 100644
--- a/packages/frontend/core/src/blocksuite/extensions/editor-config/toolbar/copy-as-image.ts
+++ b/packages/frontend/core/src/blocksuite/extensions/editor-config/toolbar/copy-as-image.ts
@@ -109,12 +109,15 @@ export function copyAsImage(std: BlockStdScope) {
notify.error({
title: I18n.t('com.affine.copy.asImage.notAvailable.title'),
message: I18n.t('com.affine.copy.asImage.notAvailable.message'),
- action: {
- label: I18n.t('com.affine.copy.asImage.notAvailable.action'),
- onClick: () => {
- window.open('https://affine.pro/download');
+ actions: [
+ {
+ key: 'download',
+ label: I18n.t('com.affine.copy.asImage.notAvailable.action'),
+ onClick: () => {
+ window.open('https://affine.pro/download');
+ },
},
- },
+ ],
});
return;
}
diff --git a/packages/frontend/core/src/blocksuite/extensions/notification-service.tsx b/packages/frontend/core/src/blocksuite/extensions/notification-service.tsx
index bd6b9c2899..e552c9d6a7 100644
--- a/packages/frontend/core/src/blocksuite/extensions/notification-service.tsx
+++ b/packages/frontend/core/src/blocksuite/extensions/notification-service.tsx
@@ -1,5 +1,6 @@
import {
Input,
+ type Notification,
notify,
toast,
type ToastOptions,
@@ -96,17 +97,25 @@ export function patchNotificationService({
throw new Error('Invalid notification accent');
}
+ const toAffineNotificationActions = (
+ actions: (typeof notification)['actions']
+ ): Notification['actions'] => {
+ if (!actions) return undefined;
+
+ return actions.map(({ label, onClick, key }) => {
+ return {
+ key,
+ label: toReactNode(label),
+ onClick,
+ };
+ });
+ };
+
const toastId = fn(
{
title: toReactNode(notification.title),
message: toReactNode(notification.message),
- footer: toReactNode(notification.footer),
- action: notification.action?.onClick
- ? {
- label: toReactNode(notification.action?.label),
- onClick: notification.action.onClick,
- }
- : undefined,
+ actions: toAffineNotificationActions(notification.actions),
onDismiss: notification.onClose,
},
{
diff --git a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.css.ts b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.css.ts
index 99b33d8b98..379433190c 100644
--- a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.css.ts
+++ b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.css.ts
@@ -20,10 +20,6 @@ export const thumbContent = style({
height: 'calc(100% + 4px)',
});
-export const actionButton = style({
- fontSize: cssVar('fontSm'),
- lineHeight: '22px',
-});
export const getStartedButtonText = style({
color: cssVar('textSecondaryColor'),
});
diff --git a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx
index b91595a812..67a479ae2d 100644
--- a/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx
+++ b/packages/frontend/core/src/components/affine/ai-onboarding/edgeless.dialog.tsx
@@ -1,4 +1,5 @@
-import { Button, FlexWrapper, notify } from '@affine/component';
+import { notify } from '@affine/component';
+import { type Notification } from '@affine/component/ui/notification';
import { SubscriptionService } from '@affine/core/modules/cloud';
import { WorkspaceDialogService } from '@affine/core/modules/dialogs';
import { EditorService } from '@affine/core/modules/editor';
@@ -63,6 +64,38 @@ export const AIOnboardingEdgeless = () => {
});
}, [workspaceDialogService]);
+ const actions = useMemo(() => {
+ const result: NonNullable = [
+ {
+ key: 'get-started',
+ label: (
+
+ {t['com.affine.ai-onboarding.edgeless.get-started']()}
+
+ ),
+ onClick: () => {
+ toggleEdgelessAIOnboarding(false);
+ },
+ },
+ ];
+
+ if (!aiSubscription) {
+ result.push({
+ key: 'purchase',
+ label: (
+
+ {t['com.affine.ai-onboarding.edgeless.purchase']()}
+
+ ),
+ onClick: () => {
+ goToPricingPlans();
+ toggleEdgelessAIOnboarding(false);
+ },
+ });
+ }
+ return result;
+ }, [aiSubscription, goToPricingPlans, t]);
+
useEffect(() => {
if (generalAIOnboardingOpened) return;
if (notifyId) return;
@@ -83,50 +116,13 @@ export const AIOnboardingEdgeless = () => {
thumb: ,
alignMessage: 'icon',
onDismiss: () => toggleEdgelessAIOnboarding(false),
- footer: (
-
-
- {aiSubscription ? null : (
-
- )}
-
- ),
+ actions,
},
{ duration: 1000 * 60 * 10 }
);
edgelessNotifyId$.next(id);
}, 1000);
- }, [
- aiSubscription,
- generalAIOnboardingOpened,
- goToPricingPlans,
- mode,
- notifyId,
- t,
- ]);
+ }, [actions, generalAIOnboardingOpened, mode, notifyId, t]);
return null;
};
diff --git a/packages/frontend/core/src/components/affine/ai-onboarding/local.dialog.tsx b/packages/frontend/core/src/components/affine/ai-onboarding/local.dialog.tsx
index 5b420e3f59..afb14fe86e 100644
--- a/packages/frontend/core/src/components/affine/ai-onboarding/local.dialog.tsx
+++ b/packages/frontend/core/src/components/affine/ai-onboarding/local.dialog.tsx
@@ -1,4 +1,4 @@
-import { Button, notify } from '@affine/component';
+import { type Notification, notify } from '@affine/component';
import {
RouteLogic,
useNavigateHelper,
@@ -8,7 +8,7 @@ import { useI18n } from '@affine/i18n';
import { AiIcon } from '@blocksuite/icons/rc';
import { useLiveData, useService } from '@toeverything/infra';
import { cssVar } from '@toeverything/theme';
-import { useEffect, useRef } from 'react';
+import { useEffect, useMemo, useRef } from 'react';
import { toggleLocalAIOnboarding } from './apis';
import * as styles from './local.dialog.css';
@@ -29,51 +29,41 @@ const LocalOnboardingAnimation = () => {
);
};
-const FooterActions = ({ onDismiss }: { onDismiss: () => void }) => {
- const t = useI18n();
- const authService = useService(AuthService);
- const loginStatus = useLiveData(authService.session.status$);
- const loggedIn = loginStatus === 'authenticated';
- const { jumpToSignIn } = useNavigateHelper();
-
- return (
-
- );
-};
-
export const AIOnboardingLocal = () => {
const t = useI18n();
const authService = useService(AuthService);
const notifyId = useLiveData(localNotifyId$);
const timeoutRef = useRef | null>(null);
+ const { jumpToSignIn } = useNavigateHelper();
const loginStatus = useLiveData(authService.session.status$);
const notSignedIn = loginStatus !== 'authenticated';
+ const actions = useMemo(() => {
+ const result: NonNullable = [
+ {
+ key: 'learn-more',
+ label: t['com.affine.ai-onboarding.local.action-learn-more'](),
+ onClick: () => {
+ window.open('https://ai.affine.pro', '_blank', 'noreferrer');
+ },
+ },
+ ];
+ if (notSignedIn) {
+ result.push({
+ key: 'get-started',
+ label: t['com.affine.ai-onboarding.local.action-get-started'](),
+ onClick: () => {
+ jumpToSignIn('', RouteLogic.REPLACE, {}, { initCloud: 'true' });
+ },
+ });
+ }
+
+ return result;
+ }, [t, jumpToSignIn, notSignedIn]);
+
useEffect(() => {
- if (!notSignedIn) return;
+ // if (!notSignedIn) return;
if (notifyId) return;
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
@@ -95,21 +85,14 @@ export const AIOnboardingLocal = () => {
thumb: ,
alignMessage: 'icon',
onDismiss: () => toggleLocalAIOnboarding(false),
- footer: (
- {
- toggleLocalAIOnboarding(false);
- notify.dismiss(id);
- }}
- />
- ),
+ actions,
rootAttrs: { className: styles.card },
},
{ duration: 1000 * 60 * 10 }
);
localNotifyId$.next(id);
}, 1000);
- }, [notSignedIn, notifyId, t]);
+ }, [actions, notSignedIn, notifyId, t]);
return null;
};
diff --git a/packages/frontend/core/src/components/affine/subscription-landing/notify.css.ts b/packages/frontend/core/src/components/affine/subscription-landing/notify.css.ts
index 37e544dc73..bd893afd20 100644
--- a/packages/frontend/core/src/components/affine/subscription-landing/notify.css.ts
+++ b/packages/frontend/core/src/components/affine/subscription-landing/notify.css.ts
@@ -6,13 +6,6 @@ export const notifyHeader = style({
fontSize: 15,
});
-export const notifyFooter = style({
- display: 'flex',
- justifyContent: 'end',
- gap: 12,
- paddingTop: 8,
-});
-
export const actionButton = style({
fontSize: cssVar('fontSm'),
fontWeight: 500,
diff --git a/packages/frontend/core/src/components/affine/subscription-landing/notify.tsx b/packages/frontend/core/src/components/affine/subscription-landing/notify.tsx
index 973349aff2..737832001c 100644
--- a/packages/frontend/core/src/components/affine/subscription-landing/notify.tsx
+++ b/packages/frontend/core/src/components/affine/subscription-landing/notify.tsx
@@ -1,4 +1,4 @@
-import { Button, notify } from '@affine/component';
+import { type Notification, notify } from '@affine/component';
import { useI18n } from '@affine/i18n';
import clsx from 'clsx';
import { useCallback, useRef } from 'react';
@@ -7,48 +7,9 @@ import {
actionButton,
cancelButton,
confirmButton,
- notifyFooter,
notifyHeader,
} from './notify.css';
-interface SubscriptionChangedNotifyFooterProps {
- onCancel: () => void;
- onConfirm?: () => void;
- to: string;
- okText: string;
- cancelText: string;
-}
-
-const SubscriptionChangedNotifyFooter = ({
- to,
- okText,
- cancelText,
- onCancel,
- onConfirm,
-}: SubscriptionChangedNotifyFooterProps) => {
- return (
-
- );
-};
-
export const useDowngradeNotify = () => {
const t = useI18n();
const prevNotifyIdRef = useRef(null);
@@ -56,6 +17,30 @@ export const useDowngradeNotify = () => {
return useCallback(
(link: string) => {
prevNotifyIdRef.current && notify.dismiss(prevNotifyIdRef.current);
+
+ const actions: Notification['actions'] = [
+ {
+ key: 'later',
+ label: t['com.affine.payment.downgraded-notify.later'](),
+ onClick: () => {},
+ buttonProps: {
+ className: clsx(actionButton, cancelButton),
+ },
+ },
+ {
+ key: 'ok',
+ label: BUILD_CONFIG.isElectron
+ ? t['com.affine.payment.downgraded-notify.ok-client']()
+ : t['com.affine.payment.downgraded-notify.ok-web'](),
+ onClick: () => {
+ window.open(link, '_blank', 'noreferrer');
+ },
+ buttonProps: {
+ className: clsx(actionButton, confirmButton),
+ },
+ },
+ ];
+
const id = notify(
{
title: (
@@ -66,19 +51,7 @@ export const useDowngradeNotify = () => {
message: t['com.affine.payment.downgraded-notify.content'](),
alignMessage: 'title',
icon: null,
- footer: (
- notify.dismiss(id)}
- onConfirm={() => notify.dismiss(id)}
- />
- ),
+ actions,
},
{ duration: 24 * 60 * 60 * 1000 }
);
diff --git a/packages/frontend/core/src/components/over-capacity/index.tsx b/packages/frontend/core/src/components/over-capacity/index.tsx
index 96c0ffcf7e..bab286adac 100644
--- a/packages/frontend/core/src/components/over-capacity/index.tsx
+++ b/packages/frontend/core/src/components/over-capacity/index.tsx
@@ -43,10 +43,13 @@ export const OverCapacityNotification = () => {
title: t['com.affine.payment.storage-limit.new-title'](),
message:
t['com.affine.payment.storage-limit.new-description.owner'](),
- action: {
- label: t['com.affine.payment.upgrade'](),
- onClick: jumpToPricePlan,
- },
+ actions: [
+ {
+ key: 'upgrade',
+ label: t['com.affine.payment.upgrade'](),
+ onClick: jumpToPricePlan,
+ },
+ ],
});
} else {
notify.warning({
diff --git a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/backup/index.tsx b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/backup/index.tsx
index 79a46e829c..7f93c52efc 100644
--- a/packages/frontend/core/src/desktop/dialogs/setting/general-setting/backup/index.tsx
+++ b/packages/frontend/core/src/desktop/dialogs/setting/general-setting/backup/index.tsx
@@ -87,14 +87,17 @@ const BackupWorkspaceItem = ({ item }: { item: BackupWorkspaceItem }) => {
}
notify.success({
title: t['com.affine.settings.workspace.backup.import.success'](),
- action: {
- label:
- t['com.affine.settings.workspace.backup.import.success.action'](),
- onClick: () => {
- jumpToPage(workspaceId, 'all');
+ actions: [
+ {
+ key: 'open',
+ label:
+ t['com.affine.settings.workspace.backup.import.success.action'](),
+ onClick: () => {
+ jumpToPage(workspaceId, 'all');
+ },
+ autoClose: false,
},
- autoClose: false,
- },
+ ],
});
setMenuOpen(false);
setImporting(false);
diff --git a/packages/frontend/core/src/modules/at-menu-config/services/index.ts b/packages/frontend/core/src/modules/at-menu-config/services/index.ts
index 6c63eee722..804d7498ee 100644
--- a/packages/frontend/core/src/modules/at-menu-config/services/index.ts
+++ b/packages/frontend/core/src/modules/at-menu-config/services/index.ts
@@ -459,45 +459,49 @@ export class AtMenuConfigService extends Service {
]({
username,
}),
- action: {
- label: 'Invite',
- onClick: async () => {
- track.$.sharePanel.$.inviteUserDocRole({
- control: 'member list',
- role: 'reader',
- });
-
- try {
- await this.docGrantedUsersService.updateUserRole(
- id,
- DocRole.Reader
- );
-
- await notificationService.mentionUser(
- id,
- workspaceId,
- {
- id: docId,
- title:
- this.docDisplayMetaService.title$(docId).value,
- blockId: block.blockId,
- mode: mode as GraphqlDocMode,
- }
- );
-
- notify.success({
- title: I18n.t(
- 'com.affine.editor.at-menu.invited-and-notified'
- ),
+ actions: [
+ {
+ key: 'invite',
+ label: 'Invite',
+ onClick: async () => {
+ track.$.sharePanel.$.inviteUserDocRole({
+ control: 'member list',
+ role: 'reader',
});
- } catch (error) {
- const err = UserFriendlyError.fromAny(error);
- notify.error({
- title: I18n[`error.${err.name}`](err.data),
- });
- }
+
+ try {
+ await this.docGrantedUsersService.updateUserRole(
+ id,
+ DocRole.Reader
+ );
+
+ await notificationService.mentionUser(
+ id,
+ workspaceId,
+ {
+ id: docId,
+ title:
+ this.docDisplayMetaService.title$(docId)
+ .value,
+ blockId: block.blockId,
+ mode: mode as GraphqlDocMode,
+ }
+ );
+
+ notify.success({
+ title: I18n.t(
+ 'com.affine.editor.at-menu.invited-and-notified'
+ ),
+ });
+ } catch (error) {
+ const err = UserFriendlyError.fromAny(error);
+ notify.error({
+ title: I18n[`error.${err.name}`](err.data),
+ });
+ }
+ },
},
- },
+ ],
});
} else {
notify.error({
diff --git a/tests/affine-local/e2e/blocksuite/edgeless/note.spec.ts b/tests/affine-local/e2e/blocksuite/edgeless/note.spec.ts
index 7febc3fe85..6391ac2733 100644
--- a/tests/affine-local/e2e/blocksuite/edgeless/note.spec.ts
+++ b/tests/affine-local/e2e/blocksuite/edgeless/note.spec.ts
@@ -243,14 +243,14 @@ test.describe('edgeless note element toolbar', () => {
await displayInPage.click();
await locateModeSwitchButton(page, 'page').click();
- expect(notes).toHaveCount(2);
+ await expect(notes).toHaveCount(2);
await clickEdgelessModeButton(page);
await clickView(page, [100, 100]);
await displayInPage.click();
await locateModeSwitchButton(page, 'page').click();
await waitForEditorLoad(page);
- expect(notes).toHaveCount(1);
+ await expect(notes).toHaveCount(1);
const undoButton = page.getByTestId('undo-display-in-page');
const viewTocButton = page.getByTestId('view-in-toc');
@@ -259,14 +259,14 @@ test.describe('edgeless note element toolbar', () => {
await waitForEditorLoad(page);
await clickView(page, [100, 100]);
await displayInPage.click();
- expect(undoButton).toBeVisible();
- expect(viewTocButton).toBeVisible();
+ await expect(undoButton).toBeVisible();
+ await expect(viewTocButton).toBeVisible();
await undoButton.click();
await expect(undoButton).toBeHidden();
await locateModeSwitchButton(page, 'page').click();
await waitForEditorLoad(page);
- expect(notes).toHaveCount(1);
+ await expect(notes).toHaveCount(1);
await clickEdgelessModeButton(page);
await waitForEditorLoad(page);
@@ -274,7 +274,7 @@ test.describe('edgeless note element toolbar', () => {
await displayInPage.click();
await undoByKeyboard(page);
await page.waitForTimeout(500);
- expect(
+ await expect(
undoButton,
'the toast should be hidden immediately when undo by keyboard'
).toBeHidden();
@@ -286,7 +286,7 @@ test.describe('edgeless note element toolbar', () => {
const highlightNoteCards = toc.locator(
'affine-outline-note-card > [data-status="selected"]'
);
- expect(highlightNoteCards).toHaveCount(1);
+ await expect(highlightNoteCards).toHaveCount(1);
});
test('note edgeless styles', async ({ page }) => {