mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-09-06 08:50:50 +08:00
refactor(component): adapt the questionnaire component to the desktop client (#5514)
close TOV-240 Windows desktop: <img width="1145" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/6b12a6bd-c020-4d02-a366-e97e1afd1e10"> MacOS desktop: <img width="1187" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/9a3c909c-b283-4ddc-a187-3db12b26a7f5"> Web: <img width="1438" alt="image" src="https://github.com/toeverything/AFFiNE/assets/102217452/e8e04258-9275-470d-a3f8-5d18f5b29eb3">
This commit is contained in:
@@ -1,28 +1,65 @@
|
|||||||
import { globalStyle, style } from '@vanilla-extract/css';
|
import { globalStyle, style } from '@vanilla-extract/css';
|
||||||
|
|
||||||
|
export const layout = style({
|
||||||
|
backgroundColor: 'var(--affine-background-primary-color)',
|
||||||
|
height: '100vh',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
overflow: 'hidden',
|
||||||
|
selectors: {
|
||||||
|
'&[data-is-macos-electron="true"]': {
|
||||||
|
margin: '8px',
|
||||||
|
borderRadius: '8px',
|
||||||
|
height: 'calc(100vh - 16px)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const header = style({
|
||||||
|
paddingTop: '24px',
|
||||||
|
paddingRight: '24px',
|
||||||
|
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'flex-end',
|
||||||
|
['WebkitAppRegion' as string]: 'drag',
|
||||||
|
selectors: {
|
||||||
|
'&[data-is-windows-electron="true"]': {
|
||||||
|
paddingTop: '0',
|
||||||
|
paddingRight: '0',
|
||||||
|
gap: '16px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
export const footer = style({
|
||||||
|
padding: '20px',
|
||||||
|
position: 'sticky',
|
||||||
|
bottom: 0,
|
||||||
|
backgroundColor: 'var(--affine-background-primary-color)',
|
||||||
|
});
|
||||||
|
|
||||||
export const scrollableContainer = style({
|
export const scrollableContainer = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'center',
|
justifyContent: 'center',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
height: '100vh',
|
padding: '80px 200px 160px',
|
||||||
padding: '0 200px',
|
|
||||||
backgroundColor: 'var(--affine-background-primary-color)',
|
|
||||||
'@media': {
|
'@media': {
|
||||||
'screen and (max-width: 1024px)': {
|
'screen and (max-width: 1024px)': {
|
||||||
padding: '80px 36px',
|
padding: '0px 36px 80px',
|
||||||
alignItems: 'center',
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const onboardingContainer = style({
|
export const onboardingContainer = style({
|
||||||
maxWidth: '600px',
|
maxWidth: '600px',
|
||||||
padding: '160px 0',
|
|
||||||
'@media': {
|
'@media': {
|
||||||
'screen and (max-width: 1024px)': {
|
'screen and (max-width: 1024px)': {
|
||||||
padding: '40px 0',
|
padding: '40px 0',
|
||||||
width: '100%',
|
maxWidth: '100%',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -49,7 +86,6 @@ export const optionsWrapper = style({
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
alignItems: 'flex-start',
|
alignItems: 'flex-start',
|
||||||
gap: '16px',
|
gap: '16px',
|
||||||
// flexShrink: 0,
|
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -95,10 +131,13 @@ export const openAFFiNEButton = style({
|
|||||||
alignSelf: 'flex-start',
|
alignSelf: 'flex-start',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const rightCornerButton = style({
|
export const disableButton = style({
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '24px',
|
display: 'none',
|
||||||
right: '24px',
|
pointerEvents: 'none',
|
||||||
|
});
|
||||||
|
export const windowsAppButton = style({
|
||||||
|
marginRight: '24px',
|
||||||
});
|
});
|
||||||
|
|
||||||
export const thankContainer = style({
|
export const thankContainer = style({
|
||||||
@@ -122,9 +161,6 @@ export const thankText = style({
|
|||||||
|
|
||||||
export const linkGroup = style({
|
export const linkGroup = style({
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
position: 'absolute',
|
|
||||||
bottom: '24px',
|
|
||||||
right: '24px',
|
|
||||||
fontSize: 'var(--affine-font-xs)',
|
fontSize: 'var(--affine-font-xs)',
|
||||||
height: '16px',
|
height: '16px',
|
||||||
gap: '6px',
|
gap: '6px',
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
|
import { apis } from '@affine/electron-api';
|
||||||
import { fetchWithTraceReport } from '@affine/graphql';
|
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 { useEffect, useMemo, useState } from 'react';
|
||||||
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
import { type Location, useLocation, useNavigate } from 'react-router-dom';
|
import { type Location, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
@@ -50,43 +51,60 @@ function getCallbackUrl(location: Location) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ScrollableLayout = ({
|
export const ScrollableLayout = ({
|
||||||
|
headerItems,
|
||||||
children,
|
children,
|
||||||
|
isMacosDesktop,
|
||||||
|
isWindowsDesktop,
|
||||||
}: {
|
}: {
|
||||||
|
isMacosDesktop?: boolean;
|
||||||
|
isWindowsDesktop?: boolean;
|
||||||
|
headerItems?: React.ReactNode;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<ScrollableContainer className={styles.scrollableContainer}>
|
<div className={styles.layout} data-is-macos-electron={isMacosDesktop}>
|
||||||
<div className={styles.onboardingContainer}>{children}</div>
|
<header
|
||||||
|
className={styles.header}
|
||||||
<div className={styles.linkGroup}>
|
data-is-windows-electron={isWindowsDesktop}
|
||||||
<a
|
>
|
||||||
className={styles.link}
|
{headerItems}
|
||||||
href="https://affine.pro/terms"
|
</header>
|
||||||
target="_blank"
|
<ScrollableContainer className={styles.scrollableContainer}>
|
||||||
rel="noreferrer"
|
<div className={styles.onboardingContainer}>{children}</div>
|
||||||
>
|
</ScrollableContainer>
|
||||||
Terms of Conditions
|
<footer className={styles.footer}>
|
||||||
</a>
|
<div className={styles.linkGroup}>
|
||||||
<Divider orientation="vertical" />
|
<a
|
||||||
<a
|
className={styles.link}
|
||||||
className={styles.link}
|
href="https://affine.pro/terms"
|
||||||
href="https://affine.pro/privacy"
|
target="_blank"
|
||||||
target="_blank"
|
rel="noreferrer"
|
||||||
rel="noreferrer"
|
>
|
||||||
>
|
Terms of Conditions
|
||||||
Privacy Policy
|
</a>
|
||||||
</a>
|
<Divider orientation="vertical" />
|
||||||
</div>
|
<a
|
||||||
</ScrollableContainer>
|
className={styles.link}
|
||||||
|
href="https://affine.pro/privacy"
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer"
|
||||||
|
>
|
||||||
|
Privacy Policy
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const OnboardingPage = ({
|
export const OnboardingPage = ({
|
||||||
user,
|
user,
|
||||||
onOpenAffine,
|
onOpenAffine,
|
||||||
|
windowControl,
|
||||||
}: {
|
}: {
|
||||||
user: User;
|
user: User;
|
||||||
onOpenAffine: () => void;
|
onOpenAffine: () => void;
|
||||||
|
windowControl?: React.ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@@ -104,6 +122,17 @@ export const OnboardingPage = ({
|
|||||||
() => questions?.[questionIdx],
|
() => questions?.[questionIdx],
|
||||||
[questionIdx, questions]
|
[questionIdx, questions]
|
||||||
);
|
);
|
||||||
|
const isMacosDesktop = environment.isDesktop && environment.isMacOs;
|
||||||
|
const isWindowsDesktop = environment.isDesktop && environment.isWindows;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (environment.isDesktop) {
|
||||||
|
// to hide macOS window control buttons
|
||||||
|
apis?.ui.handleSidebarVisibilityChange(false).catch(err => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
if (!questions) {
|
if (!questions) {
|
||||||
return null;
|
return null;
|
||||||
@@ -119,7 +148,25 @@ export const OnboardingPage = ({
|
|||||||
|
|
||||||
if (question) {
|
if (question) {
|
||||||
return (
|
return (
|
||||||
<ScrollableLayout>
|
<ScrollableLayout
|
||||||
|
headerItems={
|
||||||
|
<>
|
||||||
|
{isWindowsDesktop ? windowControl : null}
|
||||||
|
<Button
|
||||||
|
className={clsx(styles.button, {
|
||||||
|
[styles.disableButton]: questionIdx === 0,
|
||||||
|
[styles.windowsAppButton]: isWindowsDesktop,
|
||||||
|
})}
|
||||||
|
size="extraLarge"
|
||||||
|
onClick={() => setQuestionIdx(questions.length)}
|
||||||
|
>
|
||||||
|
Skip
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
isMacosDesktop={isMacosDesktop}
|
||||||
|
isWindowsDesktop={isWindowsDesktop}
|
||||||
|
>
|
||||||
<div className={styles.content}>
|
<div className={styles.content}>
|
||||||
<h1 className={styles.question}>{question.question}</h1>
|
<h1 className={styles.question}>{question.question}</h1>
|
||||||
<div className={styles.optionsWrapper}>
|
<div className={styles.optionsWrapper}>
|
||||||
@@ -168,7 +215,7 @@ export const OnboardingPage = ({
|
|||||||
<div className={styles.buttonWrapper}>
|
<div className={styles.buttonWrapper}>
|
||||||
<Button
|
<Button
|
||||||
className={clsx(styles.button, {
|
className={clsx(styles.button, {
|
||||||
[styles.rightCornerButton]: questionIdx !== 0,
|
[styles.disableButton]: questionIdx !== 0,
|
||||||
})}
|
})}
|
||||||
size="extraLarge"
|
size="extraLarge"
|
||||||
onClick={() => setQuestionIdx(questions.length)}
|
onClick={() => setQuestionIdx(questions.length)}
|
||||||
@@ -217,7 +264,11 @@ export const OnboardingPage = ({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<ScrollableLayout>
|
<ScrollableLayout
|
||||||
|
headerItems={isWindowsDesktop ? windowControl : null}
|
||||||
|
isMacosDesktop={isMacosDesktop}
|
||||||
|
isWindowsDesktop={isWindowsDesktop}
|
||||||
|
>
|
||||||
<div className={styles.thankContainer}>
|
<div className={styles.thankContainer}>
|
||||||
<h1 className={styles.thankTitle}>Thank you!</h1>
|
<h1 className={styles.thankTitle}>Thank you!</h1>
|
||||||
<p className={styles.thankText}>
|
<p className={styles.thankText}>
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import {
|
|||||||
import { z } from 'zod';
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { SubscriptionRedirect } from '../components/affine/auth/subscription-redirect';
|
import { SubscriptionRedirect } from '../components/affine/auth/subscription-redirect';
|
||||||
|
import { WindowsAppControls } from '../components/pure/header/windows-app-controls';
|
||||||
import { useCurrentLoginStatus } from '../hooks/affine/use-current-login-status';
|
import { useCurrentLoginStatus } from '../hooks/affine/use-current-login-status';
|
||||||
import { useCurrentUser } from '../hooks/affine/use-current-user';
|
import { useCurrentUser } from '../hooks/affine/use-current-user';
|
||||||
import { useMutation } from '../hooks/use-mutation';
|
import { useMutation } from '../hooks/use-mutation';
|
||||||
@@ -97,7 +98,13 @@ export const AuthPage = (): ReactElement | null => {
|
|||||||
|
|
||||||
switch (authType) {
|
switch (authType) {
|
||||||
case 'onboarding':
|
case 'onboarding':
|
||||||
return <OnboardingPage user={user} onOpenAffine={onOpenAffine} />;
|
return (
|
||||||
|
<OnboardingPage
|
||||||
|
user={user}
|
||||||
|
onOpenAffine={onOpenAffine}
|
||||||
|
windowControl={<WindowsAppControls />}
|
||||||
|
/>
|
||||||
|
);
|
||||||
case 'signUp': {
|
case 'signUp': {
|
||||||
return (
|
return (
|
||||||
<SignUpPage
|
<SignUpPage
|
||||||
|
|||||||
Reference in New Issue
Block a user