mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
feat: onboarding electron redirect (#5327)
This commit is contained in:
@@ -2,6 +2,8 @@ import { fetchWithTraceReport } from '@affine/graphql';
|
|||||||
import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
import { ArrowRightSmallIcon } from '@blocksuite/icons';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import { useMemo, useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
|
import { type Location, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
|
||||||
import { Button } from '../../ui/button';
|
import { Button } from '../../ui/button';
|
||||||
@@ -30,6 +32,23 @@ type QuestionnaireAnswer = {
|
|||||||
answer: string[];
|
answer: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function getCallbackUrl(location: Location) {
|
||||||
|
try {
|
||||||
|
const url =
|
||||||
|
location.state?.callbackURL ||
|
||||||
|
new URLSearchParams(location.search).get('callbackUrl');
|
||||||
|
if (typeof url === 'string' && url) {
|
||||||
|
if (!url.startsWith('http:') && !url.startsWith('https:')) {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
// we will ignore host to avoid redirect hack
|
||||||
|
const parsedUrl = new URL(url);
|
||||||
|
return parsedUrl.pathname + parsedUrl.search;
|
||||||
|
}
|
||||||
|
} catch (_) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
export const ScrollableLayout = ({
|
export const ScrollableLayout = ({
|
||||||
children,
|
children,
|
||||||
}: {
|
}: {
|
||||||
@@ -69,6 +88,8 @@ export const OnboardingPage = ({
|
|||||||
user: User;
|
user: User;
|
||||||
onOpenAffine: () => void;
|
onOpenAffine: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const location = useLocation();
|
||||||
|
const navigate = useNavigate();
|
||||||
const [questionIdx, setQuestionIdx] = useState(0);
|
const [questionIdx, setQuestionIdx] = useState(0);
|
||||||
const { data: questions } = useSWR<Question[]>(
|
const { data: questions } = useSWR<Question[]>(
|
||||||
'/api/worker/questionnaire',
|
'/api/worker/questionnaire',
|
||||||
@@ -78,6 +99,7 @@ export const OnboardingPage = ({
|
|||||||
const [options, setOptions] = useState(new Set<string>());
|
const [options, setOptions] = useState(new Set<string>());
|
||||||
const [inputs, setInputs] = useState<Record<string, string>>({});
|
const [inputs, setInputs] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
|
const callbackUrl = useMemo(() => getCallbackUrl(location), [location]);
|
||||||
const question = useMemo(
|
const question = useMemo(
|
||||||
() => questions?.[questionIdx],
|
() => questions?.[questionIdx],
|
||||||
[questionIdx, questions]
|
[questionIdx, questions]
|
||||||
@@ -87,6 +109,14 @@ export const OnboardingPage = ({
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callbackUrl?.startsWith('/open-app/signin-redirect')) {
|
||||||
|
const url = new URL(callbackUrl, window.location.origin);
|
||||||
|
url.searchParams.set('next', 'onboarding');
|
||||||
|
console.log('redirect to', url.toString());
|
||||||
|
window.location.assign(url.toString());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (question) {
|
if (question) {
|
||||||
return (
|
return (
|
||||||
<ScrollableLayout>
|
<ScrollableLayout>
|
||||||
@@ -198,7 +228,13 @@ export const OnboardingPage = ({
|
|||||||
className={clsx(styles.button, styles.openAFFiNEButton)}
|
className={clsx(styles.button, styles.openAFFiNEButton)}
|
||||||
type="primary"
|
type="primary"
|
||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
onClick={onOpenAffine}
|
onClick={() => {
|
||||||
|
if (callbackUrl) {
|
||||||
|
navigate(callbackUrl);
|
||||||
|
} else {
|
||||||
|
onOpenAffine();
|
||||||
|
}
|
||||||
|
}}
|
||||||
iconPosition="end"
|
iconPosition="end"
|
||||||
icon={<ArrowRightSmallIcon />}
|
icon={<ArrowRightSmallIcon />}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -169,13 +169,16 @@ const OpenOAuthJwt = () => {
|
|||||||
const maybeSchema = appSchemas.safeParse(params.get('schema'));
|
const maybeSchema = appSchemas.safeParse(params.get('schema'));
|
||||||
return maybeSchema.success ? maybeSchema.data : 'affine';
|
return maybeSchema.success ? maybeSchema.data : 'affine';
|
||||||
}, [params]);
|
}, [params]);
|
||||||
|
const next = useMemo(() => params.get('next'), [params]);
|
||||||
const channel = schemaToChanel[schema as Schema];
|
const channel = schemaToChanel[schema as Schema];
|
||||||
|
|
||||||
if (!currentUser || !currentUser?.token?.sessionToken) {
|
if (!currentUser || !currentUser?.token?.sessionToken) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlToOpen = `${schema}://signin-redirect?token=${currentUser.token.sessionToken}`;
|
const urlToOpen = `${schema}://signin-redirect?token=${
|
||||||
|
currentUser.token.sessionToken
|
||||||
|
}&next=${next || ''}`;
|
||||||
|
|
||||||
return <OpenAppImpl urlToOpen={urlToOpen} channel={channel} />;
|
return <OpenAppImpl urlToOpen={urlToOpen} channel={channel} />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -108,6 +108,10 @@ async function handleOauthJwt(url: string) {
|
|||||||
|
|
||||||
ipcMain.once('affine:login', () => {
|
ipcMain.once('affine:login', () => {
|
||||||
hiddenWindow?.destroy();
|
hiddenWindow?.destroy();
|
||||||
|
if (urlObj.searchParams.get('next') === 'onboarding') {
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||||
|
mainWindow.loadURL(mainWindowOrigin + '/auth/onboarding');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// hacks to refresh auth state in the main window
|
// hacks to refresh auth state in the main window
|
||||||
|
|||||||
Reference in New Issue
Block a user