mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat(core): add sign out confirm modal (#4592)
This commit is contained in:
@@ -11,6 +11,7 @@ export const openWorkspacesModalAtom = atom(false);
|
||||
export const openCreateWorkspaceModalAtom = atom<CreateWorkspaceMode>(false);
|
||||
export const openQuickSearchModalAtom = atom(false);
|
||||
export const openOnboardingModalAtom = atom(false);
|
||||
export const openSignOutModalAtom = atom(false);
|
||||
|
||||
export type SettingAtom = Pick<SettingProps, 'activeTab' | 'workspaceId'> & {
|
||||
open: boolean;
|
||||
|
||||
@@ -23,10 +23,8 @@ import {
|
||||
useState,
|
||||
} from 'react';
|
||||
|
||||
import { authAtom } from '../../../../atoms';
|
||||
import { authAtom, openSignOutModalAtom } from '../../../../atoms';
|
||||
import { useCurrentUser } from '../../../../hooks/affine/use-current-user';
|
||||
import { useNavigateHelper } from '../../../../hooks/use-navigate-helper';
|
||||
import { signOutCloud } from '../../../../utils/cloud-utils';
|
||||
import { Upload } from '../../../pure/file-upload';
|
||||
import * as style from './style.css';
|
||||
|
||||
@@ -168,8 +166,8 @@ const StoragePanel = () => {
|
||||
export const AccountSetting: FC = () => {
|
||||
const t = useAFFiNEI18N();
|
||||
const user = useCurrentUser();
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
const setAuthModal = useSetAtom(authAtom);
|
||||
const setSignOutModal = useSetAtom(openSignOutModalAtom);
|
||||
|
||||
const onChangeEmail = useCallback(() => {
|
||||
setAuthModal({
|
||||
@@ -189,6 +187,10 @@ export const AccountSetting: FC = () => {
|
||||
});
|
||||
}, [setAuthModal, user.email, user.hasPassword]);
|
||||
|
||||
const onOpenSignOutModal = useCallback(() => {
|
||||
setSignOutModal(true);
|
||||
}, [setSignOutModal]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SettingHeader
|
||||
@@ -220,13 +222,7 @@ export const AccountSetting: FC = () => {
|
||||
desc={t['com.affine.setting.sign.out.message']()}
|
||||
style={{ cursor: 'pointer' }}
|
||||
data-testid="sign-out-button"
|
||||
onClick={useCallback(() => {
|
||||
signOutCloud()
|
||||
.then(() => {
|
||||
jumpToIndex();
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [jumpToIndex])}
|
||||
onClick={onOpenSignOutModal}
|
||||
>
|
||||
<ArrowRightSmallIcon />
|
||||
</SettingRow>
|
||||
|
||||
46
apps/core/src/components/affine/sign-out-modal/index.tsx
Normal file
46
apps/core/src/components/affine/sign-out-modal/index.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import {
|
||||
ConfirmModal,
|
||||
type ConfirmModalProps,
|
||||
} from '@toeverything/components/modal';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
type SignOutConfirmModalI18NKeys =
|
||||
| 'title'
|
||||
| 'description'
|
||||
| 'cancel'
|
||||
| 'confirm';
|
||||
|
||||
export const SignOutModal = ({ ...props }: ConfirmModalProps) => {
|
||||
const { title, description, cancelText, confirmButtonOptions = {} } = props;
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
const defaultTexts = useMemo(() => {
|
||||
const getDefaultText = (key: SignOutConfirmModalI18NKeys) => {
|
||||
return t[`com.affine.auth.sign-out.confirm-modal.${key}`]();
|
||||
};
|
||||
return {
|
||||
title: getDefaultText('title'),
|
||||
description: getDefaultText('description'),
|
||||
cancelText: getDefaultText('cancel'),
|
||||
children: getDefaultText('confirm'),
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<ConfirmModal
|
||||
title={title ?? defaultTexts.title}
|
||||
description={description ?? defaultTexts.description}
|
||||
cancelText={cancelText ?? defaultTexts.cancelText}
|
||||
confirmButtonOptions={{
|
||||
type: 'error',
|
||||
['data-testid' as string]: 'confirm-sign-out-button',
|
||||
children: confirmButtonOptions.children ?? defaultTexts.children,
|
||||
}}
|
||||
contentOptions={{
|
||||
['data-testid' as string]: 'confirm-sign-out-modal',
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -10,15 +10,15 @@ import { Menu, MenuIcon, MenuItem } from '@toeverything/components/menu';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { openSettingModalAtom } from '../../../../../atoms';
|
||||
import { signOutCloud } from '../../../../../utils/cloud-utils';
|
||||
import { useNavigateHelper } from '../.././../../../hooks/use-navigate-helper';
|
||||
import {
|
||||
openSettingModalAtom,
|
||||
openSignOutModalAtom,
|
||||
} from '../../../../../atoms';
|
||||
import * as styles from './index.css';
|
||||
|
||||
const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
||||
const setSettingModalAtom = useSetAtom(openSettingModalAtom);
|
||||
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
const setOpenSignOutModalAtom = useSetAtom(openSignOutModalAtom);
|
||||
|
||||
const onOpenAccountSetting = useCallback(() => {
|
||||
setSettingModalAtom(prev => ({
|
||||
@@ -28,14 +28,10 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
||||
}));
|
||||
}, [setSettingModalAtom]);
|
||||
|
||||
const onSignOut = useCallback(async () => {
|
||||
signOutCloud()
|
||||
.then(() => {
|
||||
jumpToIndex();
|
||||
})
|
||||
.catch(console.error);
|
||||
const onOpenSignOutModal = useCallback(() => {
|
||||
onEventEnd?.();
|
||||
}, [onEventEnd, jumpToIndex]);
|
||||
setOpenSignOutModalAtom(true);
|
||||
}, [onEventEnd, setOpenSignOutModalAtom]);
|
||||
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
@@ -47,7 +43,7 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
||||
<AccountIcon />
|
||||
</MenuIcon>
|
||||
}
|
||||
data-testid="editor-option-menu-import"
|
||||
data-testid="workspace-modal-account-settings-option"
|
||||
onClick={onOpenAccountSetting}
|
||||
>
|
||||
{t['com.affine.workspace.cloud.account.settings']()}
|
||||
@@ -59,8 +55,8 @@ const AccountMenu = ({ onEventEnd }: { onEventEnd?: () => void }) => {
|
||||
<SignOutIcon />
|
||||
</MenuIcon>
|
||||
}
|
||||
data-testid="editor-option-menu-import"
|
||||
onClick={onSignOut}
|
||||
data-testid="workspace-modal-sign-out-option"
|
||||
onClick={onOpenSignOutModal}
|
||||
>
|
||||
{t['com.affine.workspace.cloud.account.logout']()}
|
||||
</MenuItem>
|
||||
@@ -86,7 +82,7 @@ export const UserAccountItem = ({
|
||||
}}
|
||||
>
|
||||
<IconButton
|
||||
data-testid="more-button"
|
||||
data-testid="workspace-modal-account-option"
|
||||
icon={<MoreHorizontalIcon />}
|
||||
type="plain"
|
||||
/>
|
||||
|
||||
@@ -2,36 +2,52 @@ import { NotFoundPage } from '@affine/component/not-found-page';
|
||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||
import { useSession } from 'next-auth/react';
|
||||
import type { ReactElement } from 'react';
|
||||
import { useCallback } from 'react';
|
||||
import { useCallback, useState } from 'react';
|
||||
|
||||
import { SignOutModal } from '../components/affine/sign-out-modal';
|
||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { signOutCloud } from '../utils/cloud-utils';
|
||||
|
||||
export const Component = (): ReactElement => {
|
||||
const { data: session } = useSession();
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleBackButtonClick = useCallback(
|
||||
() => jumpToIndex(RouteLogic.REPLACE),
|
||||
[jumpToIndex]
|
||||
);
|
||||
const handleSignOut = useCallback(async () => {
|
||||
|
||||
const handleOpenSignOutModal = useCallback(() => {
|
||||
setOpen(true);
|
||||
}, [setOpen]);
|
||||
|
||||
const onConfirmSignOut = useCallback(async () => {
|
||||
setOpen(false);
|
||||
await signOutCloud({
|
||||
callbackUrl: '/signIn',
|
||||
});
|
||||
}, []);
|
||||
}, [setOpen]);
|
||||
return (
|
||||
<NotFoundPage
|
||||
user={
|
||||
session?.user
|
||||
? {
|
||||
name: session.user.name || '',
|
||||
email: session.user.email || '',
|
||||
avatar: session.user.image || '',
|
||||
}
|
||||
: null
|
||||
}
|
||||
onBack={handleBackButtonClick}
|
||||
onSignOut={handleSignOut}
|
||||
/>
|
||||
<>
|
||||
<NotFoundPage
|
||||
user={
|
||||
session?.user
|
||||
? {
|
||||
name: session.user.name || '',
|
||||
email: session.user.email || '',
|
||||
avatar: session.user.image || '',
|
||||
}
|
||||
: null
|
||||
}
|
||||
onBack={handleBackButtonClick}
|
||||
onSignOut={handleOpenSignOutModal}
|
||||
/>
|
||||
<SignOutModal
|
||||
open={open}
|
||||
onOpenChange={setOpen}
|
||||
onConfirm={onConfirmSignOut}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,9 +10,11 @@ import {
|
||||
openCreateWorkspaceModalAtom,
|
||||
openDisableCloudAlertModalAtom,
|
||||
openSettingModalAtom,
|
||||
openSignOutModalAtom,
|
||||
} from '../atoms';
|
||||
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
||||
import { useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { signOutCloud } from '../utils/cloud-utils';
|
||||
|
||||
const SettingModal = lazy(() =>
|
||||
import('../components/affine/setting-modal').then(module => ({
|
||||
@@ -45,6 +47,12 @@ const OnboardingModal = lazy(() =>
|
||||
}))
|
||||
);
|
||||
|
||||
const SignOutModal = lazy(() =>
|
||||
import('../components/affine/sign-out-modal').then(module => ({
|
||||
default: module.SignOutModal,
|
||||
}))
|
||||
);
|
||||
|
||||
export const Setting = () => {
|
||||
const [currentWorkspace] = useCurrentWorkspace();
|
||||
const [{ open, workspaceId, activeTab }, setOpenSettingModalAtom] =
|
||||
@@ -141,6 +149,24 @@ export function CurrentWorkspaceModals() {
|
||||
);
|
||||
}
|
||||
|
||||
export const SignOutConfirmModal = () => {
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
const [open, setOpen] = useAtom(openSignOutModalAtom);
|
||||
|
||||
const onConfirm = useCallback(async () => {
|
||||
setOpen(false);
|
||||
signOutCloud()
|
||||
.then(() => {
|
||||
jumpToIndex();
|
||||
})
|
||||
.catch(console.error);
|
||||
}, [jumpToIndex, setOpen]);
|
||||
|
||||
return (
|
||||
<SignOutModal open={open} onOpenChange={setOpen} onConfirm={onConfirm} />
|
||||
);
|
||||
};
|
||||
|
||||
export const AllWorkspaceModals = (): ReactElement => {
|
||||
const [isOpenCreateWorkspaceModal, setOpenCreateWorkspaceModal] = useAtom(
|
||||
openCreateWorkspaceModalAtom
|
||||
@@ -172,6 +198,9 @@ export const AllWorkspaceModals = (): ReactElement => {
|
||||
<Suspense>
|
||||
<AuthModal />
|
||||
</Suspense>
|
||||
<Suspense>
|
||||
<SignOutConfirmModal />
|
||||
</Suspense>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user