mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-04 08:38:34 +00: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';
|
||||
|
||||
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',
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user