mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: can not enable workspace if not sign in (#4265)
Co-authored-by: Alex Yang <himself65@outlook.com>
This commit is contained in:
25
apps/core/src/atoms/event.ts
Normal file
25
apps/core/src/atoms/event.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { atom, useAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
export type OnceSignedInEvent = () => void;
|
||||
|
||||
export const onceSignedInEventsAtom = atom<OnceSignedInEvent[]>([]);
|
||||
|
||||
export const setOnceSignedInEventAtom = atom(
|
||||
null,
|
||||
(get, set, event: OnceSignedInEvent) => {
|
||||
set(onceSignedInEventsAtom, [...get(onceSignedInEventsAtom), event]);
|
||||
}
|
||||
);
|
||||
|
||||
export const useOnceSignedInEvents = () => {
|
||||
const [events, setEvents] = useAtom(onceSignedInEventsAtom);
|
||||
return useCallback(async () => {
|
||||
try {
|
||||
await Promise.all(events.map(event => event()));
|
||||
} catch (err) {
|
||||
console.error('Error executing one of the events:', err);
|
||||
}
|
||||
setEvents([]);
|
||||
}, [events, setEvents]);
|
||||
};
|
||||
@@ -27,8 +27,6 @@ export type AuthAtom = {
|
||||
state: AuthProps['state'];
|
||||
email?: string;
|
||||
emailType?: AuthProps['emailType'];
|
||||
// Only used for sign in page callback, after called, it will be set to undefined
|
||||
onceSignedIn?: () => void;
|
||||
};
|
||||
|
||||
export const authAtom = atom<AuthAtom>({
|
||||
|
||||
@@ -2,7 +2,12 @@ import { Modal, ModalWrapper } from '@affine/component';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import { CloseIcon } from '@blocksuite/icons';
|
||||
import { Button, IconButton } from '@toeverything/components/button';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
import { authAtom } from '../../../atoms';
|
||||
import { setOnceSignedInEventAtom } from '../../../atoms/event';
|
||||
import { useCurrentLoginStatus } from '../../../hooks/affine/use-current-login-status';
|
||||
import { ButtonContainer, Content, Header, StyleTips, Title } from './style';
|
||||
|
||||
interface EnableAffineCloudModalProps {
|
||||
@@ -12,11 +17,31 @@ interface EnableAffineCloudModalProps {
|
||||
}
|
||||
|
||||
export const EnableAffineCloudModal = ({
|
||||
onConfirm,
|
||||
onConfirm: propsOnConfirm,
|
||||
open,
|
||||
onClose,
|
||||
}: EnableAffineCloudModalProps) => {
|
||||
const t = useAFFiNEI18N();
|
||||
const loginStatus = useCurrentLoginStatus();
|
||||
const setAuthAtom = useSetAtom(authAtom);
|
||||
const setOnceSignedInEvent = useSetAtom(setOnceSignedInEventAtom);
|
||||
|
||||
const confirm = useCallback(async () => {
|
||||
return propsOnConfirm();
|
||||
}, [propsOnConfirm]);
|
||||
|
||||
const onConfirm = useCallback(() => {
|
||||
if (loginStatus === 'unauthenticated') {
|
||||
setAuthAtom(prev => ({
|
||||
...prev,
|
||||
openModal: true,
|
||||
}));
|
||||
setOnceSignedInEvent(confirm);
|
||||
}
|
||||
if (loginStatus === 'authenticated') {
|
||||
return propsOnConfirm();
|
||||
}
|
||||
}, [confirm, loginStatus, propsOnConfirm, setAuthAtom, setOnceSignedInEvent]);
|
||||
|
||||
return (
|
||||
<Modal open={open} onClose={onClose} data-testid="logout-modal">
|
||||
@@ -42,7 +67,9 @@ export const EnableAffineCloudModal = ({
|
||||
block
|
||||
onClick={onConfirm}
|
||||
>
|
||||
{t['Sign in and Enable']()}
|
||||
{loginStatus === 'authenticated'
|
||||
? t['Enable']()
|
||||
: t['Sign in and Enable']()}
|
||||
</Button>
|
||||
</div>
|
||||
</ButtonContainer>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { pushNotificationAtom } from '@affine/component/notification-center';
|
||||
import type { WorkspaceRegistry } from '@affine/env/workspace';
|
||||
import type { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { WorkspaceSubPath } from '@affine/env/workspace';
|
||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||
import {
|
||||
rootWorkspacesMetadataAtom,
|
||||
workspaceAdaptersAtom,
|
||||
@@ -14,11 +16,14 @@ import { openSettingModalAtom } from '../../atoms';
|
||||
import { useNavigateHelper } from '../use-navigate-helper';
|
||||
|
||||
export function useOnTransformWorkspace() {
|
||||
const t = useAFFiNEI18N();
|
||||
const setSettingModal = useSetAtom(openSettingModalAtom);
|
||||
const WorkspaceAdapters = useAtomValue(workspaceAdaptersAtom);
|
||||
const setMetadata = useSetAtom(rootWorkspacesMetadataAtom);
|
||||
const { openPage } = useNavigateHelper();
|
||||
const currentPageId = useAtomValue(currentPageIdAtom);
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
|
||||
return useCallback(
|
||||
async <From extends WorkspaceFlavour, To extends WorkspaceFlavour>(
|
||||
from: From,
|
||||
@@ -55,8 +60,20 @@ export function useOnTransformWorkspace() {
|
||||
})
|
||||
);
|
||||
openPage(newId, currentPageId ?? WorkspaceSubPath.ALL);
|
||||
pushNotification({
|
||||
title: t['Successfully enabled AFFiNE Cloud'](),
|
||||
type: 'success',
|
||||
});
|
||||
},
|
||||
[WorkspaceAdapters, setMetadata, setSettingModal, openPage, currentPageId]
|
||||
[
|
||||
WorkspaceAdapters,
|
||||
setMetadata,
|
||||
setSettingModal,
|
||||
openPage,
|
||||
currentPageId,
|
||||
pushNotification,
|
||||
t,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@ import {
|
||||
getInviteInfoQuery,
|
||||
} from '@affine/graphql';
|
||||
import { fetcher } from '@affine/workspace/affine/gql';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useSetAtom } from 'jotai';
|
||||
import { useCallback, useEffect } from 'react';
|
||||
import { type LoaderFunction, redirect, useLoaderData } from 'react-router-dom';
|
||||
|
||||
import { authAtom } from '../atoms';
|
||||
import { setOnceSignedInEventAtom } from '../atoms/event';
|
||||
import { useCurrentLoginStatus } from '../hooks/affine/use-current-login-status';
|
||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
import { useAppHelper } from '../hooks/use-workspaces';
|
||||
@@ -51,16 +52,14 @@ export const Component = () => {
|
||||
const { addCloudWorkspace } = useAppHelper();
|
||||
const { jumpToSubPath } = useNavigateHelper();
|
||||
|
||||
const [, setAuthAtom] = useAtom(authAtom);
|
||||
const setOnceSignedInEvent = useSetAtom(setOnceSignedInEventAtom);
|
||||
|
||||
const setAuthAtom = useSetAtom(authAtom);
|
||||
const { inviteInfo } = useLoaderData() as {
|
||||
inviteId: string;
|
||||
inviteInfo: GetInviteInfoQuery['getInviteInfo'];
|
||||
};
|
||||
|
||||
const loadWorkspaceAfterSignIn = useCallback(() => {
|
||||
addCloudWorkspace(inviteInfo.workspace.id);
|
||||
}, [addCloudWorkspace, inviteInfo.workspace.id]);
|
||||
|
||||
const openWorkspace = useCallback(() => {
|
||||
addCloudWorkspace(inviteInfo.workspace.id);
|
||||
jumpToSubPath(
|
||||
@@ -73,10 +72,7 @@ export const Component = () => {
|
||||
useEffect(() => {
|
||||
if (loginStatus === 'unauthenticated') {
|
||||
// We can not pass function to navigate state, so we need to save it in atom
|
||||
setAuthAtom(prev => ({
|
||||
...prev,
|
||||
onceSignedIn: loadWorkspaceAfterSignIn,
|
||||
}));
|
||||
setOnceSignedInEvent(openWorkspace);
|
||||
jumpToSignIn(RouteLogic.REPLACE, {
|
||||
state: {
|
||||
callbackURL: `/workspace/${inviteInfo.workspace.id}/all`,
|
||||
@@ -86,9 +82,10 @@ export const Component = () => {
|
||||
}, [
|
||||
inviteInfo.workspace.id,
|
||||
jumpToSignIn,
|
||||
loadWorkspaceAfterSignIn,
|
||||
loginStatus,
|
||||
openWorkspace,
|
||||
setAuthAtom,
|
||||
setOnceSignedInEvent,
|
||||
]);
|
||||
|
||||
if (loginStatus === 'authenticated') {
|
||||
|
||||
@@ -7,6 +7,7 @@ import { useLocation, useNavigate } from 'react-router-dom';
|
||||
import { authAtom } from '../atoms';
|
||||
import { AuthPanel } from '../components/affine/auth';
|
||||
import { useCurrentLoginStatus } from '../hooks/affine/use-current-login-status';
|
||||
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
|
||||
|
||||
interface LocationState {
|
||||
state?: {
|
||||
@@ -14,36 +15,28 @@ interface LocationState {
|
||||
};
|
||||
}
|
||||
export const Component = () => {
|
||||
const [
|
||||
{ state, email = '', emailType = 'changePassword', onceSignedIn },
|
||||
setAuthAtom,
|
||||
] = useAtom(authAtom);
|
||||
const [{ state, email = '', emailType = 'changePassword' }, setAuthAtom] =
|
||||
useAtom(authAtom);
|
||||
const loginStatus = useCurrentLoginStatus();
|
||||
const location = useLocation() as LocationState;
|
||||
const navigate = useNavigate();
|
||||
const { jumpToIndex } = useNavigateHelper();
|
||||
|
||||
useEffect(() => {
|
||||
const afterSignedIn = async () => {
|
||||
if (loginStatus === 'authenticated') {
|
||||
if (onceSignedIn) {
|
||||
await onceSignedIn();
|
||||
setAuthAtom(prev => ({ ...prev, onceSignedIn: undefined }));
|
||||
}
|
||||
if (location.state?.callbackURL) {
|
||||
navigate(location.state.callbackURL, {
|
||||
replace: true,
|
||||
});
|
||||
}
|
||||
if (loginStatus === 'authenticated') {
|
||||
if (location.state?.callbackURL) {
|
||||
navigate(location.state.callbackURL, {
|
||||
replace: true,
|
||||
});
|
||||
} else {
|
||||
jumpToIndex(RouteLogic.REPLACE);
|
||||
}
|
||||
};
|
||||
afterSignedIn().catch(err => {
|
||||
console.error(err);
|
||||
});
|
||||
}
|
||||
}, [
|
||||
jumpToIndex,
|
||||
location.state?.callbackURL,
|
||||
loginStatus,
|
||||
navigate,
|
||||
onceSignedIn,
|
||||
setAuthAtom,
|
||||
]);
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ export const AuthModal = (): ReactElement => {
|
||||
{ openModal, state, email = '', emailType = 'changePassword' },
|
||||
setAuthAtom,
|
||||
] = useAtom(authAtom);
|
||||
|
||||
return (
|
||||
<Auth
|
||||
open={openModal}
|
||||
|
||||
@@ -9,11 +9,14 @@ import { useSetAtom } from 'jotai';
|
||||
import { SessionProvider, useSession } from 'next-auth/react';
|
||||
import { type PropsWithChildren, startTransition, useRef } from 'react';
|
||||
|
||||
import { useOnceSignedInEvents } from '../atoms/event';
|
||||
|
||||
const SessionReporter = () => {
|
||||
const session = useSession();
|
||||
const prevSession = useRef<ReturnType<typeof useSession>>();
|
||||
const pushNotification = useSetAtom(pushNotificationAtom);
|
||||
const refreshMetadata = useSetAtom(refreshRootMetadataAtom);
|
||||
const onceSignedInEvents = useOnceSignedInEvents();
|
||||
const t = useAFFiNEI18N();
|
||||
|
||||
if (prevSession.current !== session && session.status !== 'loading') {
|
||||
@@ -23,7 +26,9 @@ const SessionReporter = () => {
|
||||
session.status === 'authenticated'
|
||||
) {
|
||||
startTransition(() => {
|
||||
refreshMetadata();
|
||||
onceSignedInEvents().then(() => {
|
||||
refreshMetadata();
|
||||
});
|
||||
});
|
||||
pushNotification({
|
||||
title: t['com.affine.auth.has.signed'](),
|
||||
|
||||
Reference in New Issue
Block a user