feat(mobile): sign in page (#8039)

fix AF-1237
This commit is contained in:
pengx17
2024-09-04 03:58:54 +00:00
parent 0d6f468385
commit 2ac803c73f
24 changed files with 609 additions and 65 deletions

View File

@@ -15,3 +15,4 @@ export * from './sign-in-page-container';
export * from './sign-in-success-page';
export * from './sign-up-page';
export type { User } from './type';
export * from './utils';

View File

@@ -7,3 +7,5 @@ import './edgeless-template';
import { setupGlobal } from '@affine/env/global';
setupGlobal();
import '../types/types.d.ts';

View File

@@ -40,12 +40,7 @@ export function OAuth() {
);
if (!oauth) {
return (
<>
<br />
<Skeleton height={50} />
</>
);
return <Skeleton height={50} />;
}
return oauthProviders?.map(provider => (

View File

@@ -1,4 +1,3 @@
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
import type { Editor } from '@affine/core/modules/editor';
import { EditorsService } from '@affine/core/modules/editor';
import { ViewService } from '@affine/core/modules/workbench/services/view';
@@ -13,13 +12,12 @@ import {
} from '@toeverything/infra';
import {
type PropsWithChildren,
type ReactNode,
useEffect,
useLayoutEffect,
useState,
} from 'react';
import { PageNotFound } from '../../404';
const useLoadDoc = (pageId: string) => {
const currentWorkspace = useService(WorkspaceService).workspace;
const docsService = useService(DocsService);
@@ -136,15 +134,21 @@ const useLoadDoc = (pageId: string) => {
export const DetailPageWrapper = ({
pageId,
children,
}: PropsWithChildren<{ pageId: string }>) => {
skeleton,
notFound,
}: PropsWithChildren<{
pageId: string;
skeleton: ReactNode;
notFound: ReactNode;
}>) => {
const { doc, editor, docListReady } = useLoadDoc(pageId);
// if sync engine has been synced and the page is null, show 404 page.
if (docListReady && !doc) {
return <PageNotFound noPermission />;
return notFound;
}
if (!doc || !editor) {
return <PageDetailSkeleton key="current-page-is-null" />;
return skeleton;
}
return (

View File

@@ -1,4 +1,5 @@
import { Scrollable, useHasScrollTop } from '@affine/component';
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
import type { ChatPanel } from '@affine/core/blocksuite/presets/ai';
import { AIProvider } from '@affine/core/blocksuite/presets/ai';
import { PageAIOnboarding } from '@affine/core/components/affine/ai-onboarding';
@@ -53,6 +54,7 @@ import {
WorkbenchService,
} from '../../../modules/workbench';
import { performanceRenderLogger } from '../../../shared';
import { PageNotFound } from '../../404';
import * as styles from './detail-page.css';
import { DetailPageHeader } from './detail-page-header';
import { DetailPageWrapper } from './detail-page-wrapper';
@@ -347,7 +349,11 @@ export const Component = () => {
const pageId = params.pageId;
return pageId ? (
<DetailPageWrapper pageId={pageId}>
<DetailPageWrapper
pageId={pageId}
skeleton={<PageDetailSkeleton />}
notFound={<PageNotFound noPermission />}
>
<DetailPageImpl />
</DetailPageWrapper>
) : null;

View File

@@ -1,9 +1,5 @@
/// <reference types="@webpack/env"" />
// not using import because it will break the declare module line below
// eslint-disable-next-line @typescript-eslint/triple-slash-reference
/// <reference path='../../../electron/src/preload/preload.d.ts' />
declare module '*.md' {
const text: string;
export default text;
@@ -28,3 +24,8 @@ declare module '*.jpg' {
const url: string;
export default url;
}
declare module '*.inline.svg' {
const src: string;
export default src;
}

View File

@@ -1580,5 +1580,7 @@
"com.affine.mobile.setting.others.website": "Official website",
"com.affine.mobile.setting.others.privacy": "Privacy",
"com.affine.mobile.setting.others.terms": "Terms of use",
"com.affine.mobile.search.empty": "No results found"
"com.affine.mobile.search.empty": "No results found",
"com.affine.mobile.sign-in.skip.link": "Start AFFiNE without an account",
"com.affine.mobile.sign-in.skip.hint": "Want to keep data local?"
}

View File

@@ -3,7 +3,7 @@ import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const root = style({
maxHeight: 'calc(100vh - 100px)',
maxHeight: 'calc(100dvh - 100px)',
display: 'flex',
flexDirection: 'column',
});

View File

@@ -5,7 +5,6 @@ import './polyfill/request-idle-callback';
import '@affine/core/bootstrap/preload';
import { performanceLogger } from '@affine/core/shared';
import { isDesktop } from '@affine/env/constant';
import {
init,
reactRouterV6BrowserTracingIntegration,
@@ -24,36 +23,28 @@ import { App } from './app';
const performanceMainLogger = performanceLogger.namespace('main');
function main() {
performanceMainLogger.info('start');
// skip bootstrap setup for desktop onboarding
if (isDesktop && window.appInfo?.windowName === 'onboarding') {
performanceMainLogger.info('skip setup');
} else {
performanceMainLogger.info('setup start');
if (window.SENTRY_RELEASE || environment.isDebug) {
// https://docs.sentry.io/platforms/javascript/guides/react/#configure
init({
dsn: process.env.SENTRY_DSN,
environment: process.env.BUILD_TYPE ?? 'development',
integrations: [
reactRouterV6BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
});
setTags({
appVersion: runtimeConfig.appVersion,
editorVersion: runtimeConfig.editorVersion,
});
}
performanceMainLogger.info('setup done');
performanceMainLogger.info('setup start');
if (window.SENTRY_RELEASE || environment.isDebug) {
// https://docs.sentry.io/platforms/javascript/guides/react/#configure
init({
dsn: process.env.SENTRY_DSN,
environment: process.env.BUILD_TYPE ?? 'development',
integrations: [
reactRouterV6BrowserTracingIntegration({
useEffect,
useLocation,
useNavigationType,
createRoutesFromChildren,
matchRoutes,
}),
],
});
setTags({
appVersion: runtimeConfig.appVersion,
editorVersion: runtimeConfig.editorVersion,
});
}
performanceMainLogger.info('setup done');
mountApp();
}

View File

@@ -1,7 +1,37 @@
// Default route fallback for mobile
import { SignIn } from '@affine/core/pages/auth/sign-in';
import {
RouteLogic,
useNavigateHelper,
} from '@affine/core/hooks/use-navigate-helper';
import { AuthService } from '@affine/core/modules/cloud';
import { useLiveData, useService } from '@toeverything/infra';
import { useEffect } from 'react';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { MobileSignIn } from '../views/sign-in/mobile-sign-in';
export const Component = () => {
// placeholder impl
return <SignIn />;
const session = useService(AuthService).session;
const status = useLiveData(session.status$);
const isRevalidating = useLiveData(session.isRevalidating$);
const navigate = useNavigate();
const { jumpToIndex } = useNavigateHelper();
const [searchParams] = useSearchParams();
const isLoggedIn = status === 'authenticated' && !isRevalidating;
useEffect(() => {
if (isLoggedIn) {
const redirectUri = searchParams.get('redirect_uri');
if (redirectUri) {
navigate(redirectUri, {
replace: true,
});
} else {
jumpToIndex(RouteLogic.REPLACE, {
search: searchParams.toString(),
});
}
}
}, [jumpToIndex, navigate, isLoggedIn, searchParams]);
return <MobileSignIn onSkip={() => navigate('/')} />;
};

View File

@@ -4,7 +4,7 @@ import { globalStyle, style } from '@vanilla-extract/css';
export const root = style({
background: cssVarV2('layer/background/primary'),
minHeight: '100vh',
minHeight: '100dvh',
display: 'flex',
flexDirection: 'column',
});

View File

@@ -1,4 +1,5 @@
import { IconButton } from '@affine/component';
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
import { AffineErrorBoundary } from '@affine/core/components/affine/affine-error-boundary';
import { PageDetailEditor } from '@affine/core/components/page-detail-editor';
import { useRegisterBlocksuiteEditorCommands } from '@affine/core/hooks/affine/use-register-blocksuite-editor-commands';
@@ -10,6 +11,7 @@ import { EditorService } from '@affine/core/modules/editor';
import { WorkbenchService } from '@affine/core/modules/workbench';
import { ViewService } from '@affine/core/modules/workbench/services/view';
import { DetailPageWrapper } from '@affine/core/pages/workspace/detail-page/detail-page-wrapper';
import { WorkspaceFlavour } from '@affine/env/workspace';
import type { PageRootService } from '@blocksuite/blocks';
import {
BookmarkBlockService,
@@ -20,7 +22,7 @@ import {
ImageBlockService,
} from '@blocksuite/blocks';
import { DisposableGroup } from '@blocksuite/global/utils';
import { ShareIcon } from '@blocksuite/icons/rc';
import { ShareiOsIcon } from '@blocksuite/icons/rc';
import { type AffineEditorContainer } from '@blocksuite/presets';
import type { Doc as BlockSuiteDoc } from '@blocksuite/store';
import {
@@ -28,6 +30,7 @@ import {
FrameworkScope,
GlobalContextService,
useLiveData,
useService,
useServices,
WorkspaceService,
} from '@toeverything/infra';
@@ -201,9 +204,24 @@ const DetailPageImpl = () => {
);
};
const skeleton = (
<>
<PageHeader back className={styles.header} />
<PageDetailSkeleton />
</>
);
const notFound = (
<>
<PageHeader back className={styles.header} />
Page Not Found (TODO)
</>
);
export const Component = () => {
const params = useParams();
const pageId = params.pageId;
const workspace = useService(WorkspaceService).workspace;
if (!pageId) {
return null;
@@ -211,18 +229,23 @@ export const Component = () => {
return (
<div className={styles.root}>
<DetailPageWrapper pageId={pageId}>
<DetailPageWrapper
skeleton={skeleton}
notFound={notFound}
pageId={pageId}
>
<PageHeader
back
className={styles.header}
suffix={
<>
<IconButton
size={24}
style={{ padding: 10 }}
onClick={console.log}
icon={<ShareIcon />}
/>
{workspace.meta.flavour !== WorkspaceFlavour.LOCAL && (
<IconButton
size={24}
style={{ padding: 10 }}
icon={<ShareiOsIcon />}
/>
)}
<PageHeaderMenuButton docId={pageId} />
</>
}

View File

@@ -77,7 +77,7 @@ export const WorkspaceLayout = ({
return (
<FrameworkScope scope={workspace.scope}>
<AffineErrorBoundary height="100vh">
<AffineErrorBoundary height="100dvh">
<SWRConfigProvider>
<MobileCurrentWorkspaceModals />
<WorkspaceLayoutProviders>{children}</WorkspaceLayoutProviders>

View File

@@ -1,3 +1,4 @@
import { NotificationCenter } from '@affine/component';
import { AiLoginRequiredModal } from '@affine/core/components/affine/auth/ai-login-required';
import { HistoryTipsModal } from '@affine/core/components/affine/history-tips-modal';
import { IssueFeedbackModal } from '@affine/core/components/affine/issue-feedback-modal';
@@ -8,12 +9,15 @@ import {
import { StarAFFiNEModal } from '@affine/core/components/affine/star-affine-modal';
import { MoveToTrash } from '@affine/core/components/page-list';
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
import { CreateWorkspaceDialogProvider } from '@affine/core/modules/create-workspace';
import { PeekViewManagerModal } from '@affine/core/modules/peek-view';
import { SignOutConfirmModal } from '@affine/core/providers/modal-provider';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { useService, WorkspaceService } from '@toeverything/infra';
import { useCallback } from 'react';
import { MobileSettingModal } from '../views';
import { MobileSignInModal } from '../views/sign-in/modal';
export function MobileCurrentWorkspaceModals() {
const currentWorkspace = useService(WorkspaceService).workspace;
@@ -58,3 +62,15 @@ export function MobileCurrentWorkspaceModals() {
</>
);
}
// I don't like the name, but let's keep it for now
export const AllWorkspaceModals = () => {
return (
<>
<NotificationCenter />
<CreateWorkspaceDialogProvider />
<MobileSignInModal />
<SignOutConfirmModal />
</>
);
};

View File

@@ -1,9 +1,12 @@
import { RootRouter } from '@affine/core/router';
import { NavigateContext } from '@affine/core/hooks/use-navigate-helper';
import { wrapCreateBrowserRouter } from '@sentry/react';
import { useEffect, useState } from 'react';
import type { RouteObject } from 'react-router-dom';
import {
createBrowserRouter as reactRouterCreateBrowserRouter,
Outlet,
redirect,
useNavigate,
} from 'react-router-dom';
import { Component as All } from './pages/workspace/all';
@@ -13,6 +16,25 @@ import { Component as Home } from './pages/workspace/home';
import { Component as Search } from './pages/workspace/search';
import { Component as Tag } from './pages/workspace/tag';
import { Component as TagDetail } from './pages/workspace/tag/detail';
import { AllWorkspaceModals } from './provider/model-provider';
function RootRouter() {
const navigate = useNavigate();
const [ready, setReady] = useState(false);
useEffect(() => {
// a hack to make sure router is ready
setReady(true);
}, []);
return (
ready && (
<NavigateContext.Provider value={navigate}>
<AllWorkspaceModals />
<Outlet />
</NavigateContext.Provider>
)
);
}
export const topLevelRoutes = [
{

View File

@@ -0,0 +1,114 @@
<svg viewBox="0 0 393 268" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_dddd_5_8)">
<path
d="M303.627 108.436C304.395 114.603 305.588 123.539 310.979 133.694C317.042 145.118 325.33 152.128 330.252 155.717C336.082 153.95 346.218 150.065 355.707 141.278C364.144 133.467 368.217 125.424 370.974 119.854C376.695 108.297 378.944 97.1588 379.689 88.2076C374.962 87.098 368.639 85.0971 361.818 81.322C354.081 77.0403 348.645 72.0796 345.072 68.3164C340.457 70.6912 333.69 73.5828 324.975 75.0751C317.286 76.39 310.661 76.1956 305.833 75.6854C303.582 84.3809 302.038 95.6392 303.629 108.436L303.627 108.436Z"
fill="#252525" />
</g>
<g filter="url(#filter1_ddddd_5_8)">
<path
d="M-20.3209 42.0156C-22.7192 34.8601 -18.8627 27.1151 -11.7072 24.7168L50.2776 3.94111C57.4331 1.54277 65.1781 5.39922 67.5764 12.5547L77.1078 40.992L-10.7894 70.4528L-20.3209 42.0156Z"
fill="#252525" />
<path
d="M29.6583 102.94L32.3749 96.6289L31.2069 85.3674L10.9017 92.1732C3.74617 94.5715 -3.99875 90.7151 -6.39709 83.5596L-9.07716 75.5635L78.8201 46.1027L81.5002 54.0987C83.8985 61.2542 80.042 68.9992 72.8865 71.3975L52.5828 78.2028L58.4375 87.8934L64.4084 91.2923L29.6583 102.94Z"
fill="#252525" />
</g>
<g filter="url(#filter2_dddd_5_8)">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M119.605 155.688C119.605 139.292 132.995 126 149.514 126C162.899 126 174.225 134.725 178.044 146.756C193.382 148.028 205.431 160.787 205.431 176.34C205.431 192.736 192.04 206.028 175.522 206.028H128.707C115.062 206.028 104 195.048 104 181.503C104 171.091 110.534 162.201 119.751 158.641C119.654 157.669 119.605 156.683 119.605 155.688Z"
fill="#252525" />
</g>
<defs>
<filter id="filter0_dddd_5_8" x="297.976" y="64.3164" width="129.712" height="152.401"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="2" dy="3" />
<feGaussianBlur stdDeviation="3.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="7" dy="10" />
<feGaussianBlur stdDeviation="6" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="15" dy="23" />
<feGaussianBlur stdDeviation="8.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="28" dy="41" />
<feGaussianBlur stdDeviation="10" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow_5_8" result="shape" />
</filter>
<filter id="filter1_ddddd_5_8" x="-24.5953" y="0.175569" width="147.011" height="147.548"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1.52672" dy="2.03562" />
<feGaussianBlur stdDeviation="2.54453" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="6.10687" dy="7.12468" />
<feGaussianBlur stdDeviation="4.83461" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="13.7405" dy="16.7939" />
<feGaussianBlur stdDeviation="6.61578" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="24.9364" dy="29.5165" />
<feGaussianBlur stdDeviation="7.63359" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect4_dropShadow_5_8" result="effect5_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect5_dropShadow_5_8" result="shape" />
</filter>
<filter id="filter2_dddd_5_8" x="99" y="122" width="154.43" height="145.028"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="2" dy="3" />
<feGaussianBlur stdDeviation="3.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="7" dy="10" />
<feGaussianBlur stdDeviation="6" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="15" dy="23" />
<feGaussianBlur stdDeviation="8.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="28" dy="41" />
<feGaussianBlur stdDeviation="10" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow_5_8" result="shape" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,114 @@
<svg viewBox="0 0 393 268" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_dddd_5_8)">
<path
d="M303.627 108.436C304.395 114.603 305.588 123.539 310.979 133.694C317.042 145.118 325.33 152.128 330.252 155.717C336.082 153.95 346.218 150.065 355.707 141.278C364.144 133.467 368.217 125.424 370.974 119.854C376.695 108.297 378.944 97.1588 379.689 88.2076C374.962 87.098 368.639 85.0971 361.818 81.322C354.081 77.0403 348.645 72.0796 345.072 68.3164C340.457 70.6912 333.69 73.5828 324.975 75.0751C317.286 76.39 310.661 76.1956 305.833 75.6854C303.582 84.3809 302.038 95.6392 303.629 108.436L303.627 108.436Z"
fill="white" />
</g>
<g filter="url(#filter1_ddddd_5_8)">
<path
d="M-20.3209 42.0156C-22.7192 34.8601 -18.8628 27.1151 -11.7072 24.7168L50.2776 3.94111C57.4331 1.54277 65.178 5.39922 67.5764 12.5547L77.1078 40.992L-10.7894 70.4528L-20.3209 42.0156Z"
fill="white" />
<path
d="M29.6583 102.94L32.3749 96.6289L31.2069 85.3674L10.9017 92.1732C3.74617 94.5715 -3.99876 90.7151 -6.3971 83.5596L-9.07716 75.5635L78.8201 46.1027L81.5001 54.0987C83.8985 61.2542 80.042 68.9992 72.8865 71.3975L52.5828 78.2028L58.4374 87.8934L64.4084 91.2923L29.6583 102.94Z"
fill="white" />
</g>
<g filter="url(#filter2_dddd_5_8)">
<path fill-rule="evenodd" clip-rule="evenodd"
d="M119.605 155.688C119.605 139.292 132.995 126 149.514 126C162.899 126 174.225 134.725 178.044 146.756C193.382 148.028 205.431 160.787 205.431 176.34C205.431 192.736 192.04 206.028 175.522 206.028H128.707C115.062 206.028 104 195.048 104 181.503C104 171.091 110.534 162.201 119.751 158.641C119.654 157.669 119.605 156.683 119.605 155.688Z"
fill="white" />
</g>
<defs>
<filter id="filter0_dddd_5_8" x="297.976" y="64.3164" width="129.712" height="152.401"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="2" dy="3" />
<feGaussianBlur stdDeviation="3.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="7" dy="10" />
<feGaussianBlur stdDeviation="6" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="15" dy="23" />
<feGaussianBlur stdDeviation="8.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="28" dy="41" />
<feGaussianBlur stdDeviation="10" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow_5_8" result="shape" />
</filter>
<filter id="filter1_ddddd_5_8" x="-24.5953" y="0.175569" width="147.011" height="147.548"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="1.52672" dy="2.03562" />
<feGaussianBlur stdDeviation="2.54453" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="6.10687" dy="7.12468" />
<feGaussianBlur stdDeviation="4.83461" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="13.7405" dy="16.7939" />
<feGaussianBlur stdDeviation="6.61578" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="24.9364" dy="29.5165" />
<feGaussianBlur stdDeviation="7.63359" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect4_dropShadow_5_8" result="effect5_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect5_dropShadow_5_8" result="shape" />
</filter>
<filter id="filter2_dddd_5_8" x="99" y="122" width="154.431" height="145.028"
filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="2" dy="3" />
<feGaussianBlur stdDeviation="3.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0" />
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="7" dy="10" />
<feGaussianBlur stdDeviation="6" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0" />
<feBlend mode="normal" in2="effect1_dropShadow_5_8" result="effect2_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="15" dy="23" />
<feGaussianBlur stdDeviation="8.5" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.05 0" />
<feBlend mode="normal" in2="effect2_dropShadow_5_8" result="effect3_dropShadow_5_8" />
<feColorMatrix in="SourceAlpha" type="matrix"
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha" />
<feOffset dx="28" dy="41" />
<feGaussianBlur stdDeviation="10" />
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.01 0" />
<feBlend mode="normal" in2="effect3_dropShadow_5_8" result="effect4_dropShadow_5_8" />
<feBlend mode="normal" in="SourceGraphic" in2="effect4_dropShadow_5_8" result="shape" />
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,48 @@
import { createVar, globalStyle, style } from '@vanilla-extract/css';
const bgColor = createVar();
const dotColor = createVar();
export const root = style({
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
pointerEvents: 'none',
zIndex: -1,
});
export const dotBg = style({
height: '100%',
width: '100%',
position: 'absolute',
zIndex: -1,
top: 0,
left: 0,
backgroundImage: `linear-gradient(to bottom, transparent 0%, ${bgColor} 90%),
radial-gradient(${dotColor} 2px, transparent 2px),
radial-gradient(${dotColor} 2px, transparent 2px)`,
backgroundSize: '100% 100%, 20px 20px, 20px 20px',
});
export const arts = style({
paddingTop: 60,
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
});
globalStyle(`[data-theme="light"] ${root}`, {
vars: {
[bgColor]: '#fff',
[dotColor]: '#d9d9d9',
},
});
globalStyle(`[data-theme="dark"] ${root}`, {
vars: {
[bgColor]: '#141414',
[dotColor]: '#393939',
},
});

View File

@@ -0,0 +1,19 @@
import { useTheme } from 'next-themes';
import artsDark from './art-dark.inline.svg';
import artsLight from './art-light.inline.svg';
import * as styles from './background.css';
export const SignInBackground = () => {
const { resolvedTheme } = useTheme();
return (
<div className={styles.root}>
<div className={styles.dotBg} />
<img
className={styles.arts}
src={resolvedTheme === 'dark' ? artsDark : artsLight}
/>
</div>
);
};

View File

@@ -0,0 +1,61 @@
import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { style } from '@vanilla-extract/css';
export const root = style({
padding: '40px',
justifyContent: 'flex-end',
minHeight: '100dvh',
display: 'flex',
flexDirection: 'column',
position: 'relative',
zIndex: 0,
});
export const content = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'stretch',
gap: 24,
});
export const skipDivider = style({
display: 'flex',
gap: 12,
alignItems: 'center',
height: 20,
marginTop: 12,
marginBottom: 12,
});
export const skipDividerLine = style({
flex: 1,
height: 0,
borderBottom: `1px solid ${cssVarV2('layer/insideBorder/border')}`,
});
export const skipDividerText = style({
color: cssVarV2('text/secondary'),
fontSize: cssVar('fontXs'),
});
export const skipText = style({
color: cssVarV2('text/primary'),
fontSize: cssVar('fontXs'),
fontWeight: 500,
});
export const skipLink = style({
color: cssVarV2('text/link'),
fontSize: cssVar('fontXs'),
});
export const skipLinkIcon = style({
color: cssVarV2('text/link'),
});
export const skipSection = style({
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
});

View File

@@ -0,0 +1,40 @@
import { Button } from '@affine/component';
import { useI18n } from '@affine/i18n';
import { ArrowRightBigIcon } from '@blocksuite/icons/rc';
import type { PropsWithChildren } from 'react';
import { SignInBackground } from './background';
import * as styles from './layout.css';
export const MobileSignInLayout = ({
children,
onSkip,
}: PropsWithChildren<{
onSkip: () => void;
}>) => {
const t = useI18n();
return (
<div className={styles.root}>
<SignInBackground />
<div className={styles.content}>{children}</div>
<div className={styles.skipDivider}>
<div className={styles.skipDividerLine} />
<span className={styles.skipDividerText}>or</span>
<div className={styles.skipDividerLine} />
</div>
<div className={styles.skipSection}>
<div className={styles.skipText}>
{t['com.affine.mobile.sign-in.skip.hint']()}
</div>
<Button
variant="plain"
onClick={onSkip}
className={styles.skipLink}
suffix={<ArrowRightBigIcon className={styles.skipLinkIcon} />}
>
{t['com.affine.mobile.sign-in.skip.link']()}
</Button>
</div>
</div>
);
};

View File

@@ -0,0 +1,11 @@
import { AuthPanel } from '@affine/core/components/affine/auth';
import { MobileSignInLayout } from './layout';
export const MobileSignIn = ({ onSkip }: { onSkip: () => void }) => {
return (
<MobileSignInLayout onSkip={onSkip}>
<AuthPanel />
</MobileSignInLayout>
);
};

View File

@@ -0,0 +1,40 @@
import { Modal } from '@affine/component';
import { authAtom } from '@affine/core/atoms';
import { cssVarV2 } from '@toeverything/theme/v2';
import { useAtom } from 'jotai';
import { useCallback } from 'react';
import { MobileSignIn } from './mobile-sign-in';
export const MobileSignInModal = () => {
const [authAtomValue, setAuthAtom] = useAtom(authAtom);
const setOpen = useCallback(
(open: boolean) => {
setAuthAtom(prev => ({ ...prev, openModal: open }));
},
[setAuthAtom]
);
const closeModal = useCallback(() => {
setOpen(false);
}, [setOpen]);
return (
<Modal
fullScreen
animation="slideBottom"
open={authAtomValue.openModal}
onOpenChange={setOpen}
contentOptions={{
style: {
padding: 0,
overflowY: 'auto',
backgroundColor: cssVarV2('layer/background/secondary'),
},
}}
withoutCloseButton
>
<MobileSignIn onSkip={closeModal} />
</Modal>
);
};