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:
JimmFly
2024-01-19 10:07:18 +00:00
parent fa8655e43e
commit 353b27d796
3 changed files with 136 additions and 42 deletions

View File

@@ -1,28 +1,65 @@
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({
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
height: '100vh',
padding: '0 200px',
backgroundColor: 'var(--affine-background-primary-color)',
padding: '80px 200px 160px',
'@media': {
'screen and (max-width: 1024px)': {
padding: '80px 36px',
alignItems: 'center',
padding: '0px 36px 80px',
},
},
});
export const onboardingContainer = style({
maxWidth: '600px',
padding: '160px 0',
'@media': {
'screen and (max-width: 1024px)': {
padding: '40px 0',
width: '100%',
maxWidth: '100%',
},
},
});
@@ -49,7 +86,6 @@ export const optionsWrapper = style({
flexDirection: 'column',
alignItems: 'flex-start',
gap: '16px',
// flexShrink: 0,
flexGrow: 1,
});
@@ -95,10 +131,13 @@ export const openAFFiNEButton = style({
alignSelf: 'flex-start',
});
export const rightCornerButton = style({
export const disableButton = style({
position: 'absolute',
top: '24px',
right: '24px',
display: 'none',
pointerEvents: 'none',
});
export const windowsAppButton = style({
marginRight: '24px',
});
export const thankContainer = style({
@@ -122,9 +161,6 @@ export const thankText = style({
export const linkGroup = style({
display: 'flex',
position: 'absolute',
bottom: '24px',
right: '24px',
fontSize: 'var(--affine-font-xs)',
height: '16px',
gap: '6px',

View File

@@ -1,7 +1,8 @@
import { apis } from '@affine/electron-api';
import { fetchWithTraceReport } from '@affine/graphql';
import { ArrowRightSmallIcon } from '@blocksuite/icons';
import clsx from 'clsx';
import { useMemo, useState } from 'react';
import { useEffect, 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';
@@ -50,43 +51,60 @@ function getCallbackUrl(location: Location) {
}
export const ScrollableLayout = ({
headerItems,
children,
isMacosDesktop,
isWindowsDesktop,
}: {
isMacosDesktop?: boolean;
isWindowsDesktop?: boolean;
headerItems?: React.ReactNode;
children: React.ReactNode;
}) => {
return (
<ScrollableContainer className={styles.scrollableContainer}>
<div className={styles.onboardingContainer}>{children}</div>
<div className={styles.linkGroup}>
<a
className={styles.link}
href="https://affine.pro/terms"
target="_blank"
rel="noreferrer"
>
Terms of Conditions
</a>
<Divider orientation="vertical" />
<a
className={styles.link}
href="https://affine.pro/privacy"
target="_blank"
rel="noreferrer"
>
Privacy Policy
</a>
</div>
</ScrollableContainer>
<div className={styles.layout} data-is-macos-electron={isMacosDesktop}>
<header
className={styles.header}
data-is-windows-electron={isWindowsDesktop}
>
{headerItems}
</header>
<ScrollableContainer className={styles.scrollableContainer}>
<div className={styles.onboardingContainer}>{children}</div>
</ScrollableContainer>
<footer className={styles.footer}>
<div className={styles.linkGroup}>
<a
className={styles.link}
href="https://affine.pro/terms"
target="_blank"
rel="noreferrer"
>
Terms of Conditions
</a>
<Divider orientation="vertical" />
<a
className={styles.link}
href="https://affine.pro/privacy"
target="_blank"
rel="noreferrer"
>
Privacy Policy
</a>
</div>
</footer>
</div>
);
};
export const OnboardingPage = ({
user,
onOpenAffine,
windowControl,
}: {
user: User;
onOpenAffine: () => void;
windowControl?: React.ReactNode;
}) => {
const location = useLocation();
const navigate = useNavigate();
@@ -104,6 +122,17 @@ export const OnboardingPage = ({
() => questions?.[questionIdx],
[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) {
return null;
@@ -119,7 +148,25 @@ export const OnboardingPage = ({
if (question) {
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}>
<h1 className={styles.question}>{question.question}</h1>
<div className={styles.optionsWrapper}>
@@ -168,7 +215,7 @@ export const OnboardingPage = ({
<div className={styles.buttonWrapper}>
<Button
className={clsx(styles.button, {
[styles.rightCornerButton]: questionIdx !== 0,
[styles.disableButton]: questionIdx !== 0,
})}
size="extraLarge"
onClick={() => setQuestionIdx(questions.length)}
@@ -217,7 +264,11 @@ export const OnboardingPage = ({
);
}
return (
<ScrollableLayout>
<ScrollableLayout
headerItems={isWindowsDesktop ? windowControl : null}
isMacosDesktop={isMacosDesktop}
isWindowsDesktop={isWindowsDesktop}
>
<div className={styles.thankContainer}>
<h1 className={styles.thankTitle}>Thank you!</h1>
<p className={styles.thankText}>

View File

@@ -27,6 +27,7 @@ import {
import { z } from 'zod';
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 { useCurrentUser } from '../hooks/affine/use-current-user';
import { useMutation } from '../hooks/use-mutation';
@@ -97,7 +98,13 @@ export const AuthPage = (): ReactElement | null => {
switch (authType) {
case 'onboarding':
return <OnboardingPage user={user} onOpenAffine={onOpenAffine} />;
return (
<OnboardingPage
user={user}
onOpenAffine={onOpenAffine}
windowControl={<WindowsAppControls />}
/>
);
case 'signUp': {
return (
<SignUpPage