feat: router & block preview

This commit is contained in:
DarkSky 2022-07-24 21:56:03 +08:00
parent 4f1c47a3bc
commit a4132f5f8a
8 changed files with 153 additions and 100 deletions

View File

@ -1,7 +1,6 @@
/* eslint-disable filename-rules/match */
import { useCallback, useMemo } from 'react';
import { useCallback, useMemo, useState } from 'react';
import { initializeApp } from 'firebase/app';
import { Error } from './../error';
import {
GoogleAuthProvider,
getAuth,
@ -13,11 +12,12 @@ import { LogoImg } from '@toeverything/components/common';
import {
MuiButton,
MuiBox,
MuiTypography,
MuiContainer,
MuiGrid,
MuiSnackbar,
} from '@toeverything/components/ui';
import { Error } from './../error';
const _firebaseConfig = {
apiKey: 'AIzaSyD7A_VyGaKTXsPqtga9IbwrEsbWWc4rH3Y',
authDomain: 'login.affine.pro',
@ -83,6 +83,8 @@ export const Firebase = () => {
return [auth, provider];
}, []);
const [error, setError] = useState(false);
const handleAuth = useCallback(() => {
signInWithPopup(auth, provider).catch(error => {
const errorCode = error.code;
@ -90,11 +92,18 @@ export const Firebase = () => {
const email = error.customData.email;
const credential = GoogleAuthProvider.credentialFromError(error);
console.log(errorCode, errorMessage, email, credential);
setError(true);
setTimeout(() => setError(false), 3000);
});
}, [auth, provider]);
return (
<MuiGrid container>
<MuiSnackbar
anchorOrigin={{ vertical: 'top', horizontal: 'right' }}
open={error}
message="Login failed, please check if you have permission"
/>
<MuiGrid item xs={8}>
<Error
title="Welcome to Affine"

View File

@ -32,6 +32,7 @@
"code-example": "^3.3.6",
"codemirror": "6.0.1",
"keymap": "link:@codemirror/next/keymap",
"nanoid": "^4.0.0",
"react-resizable": "^3.0.4",
"react-window": "^1.8.7",
"slate": "^0.81.1",

View File

@ -0,0 +1,132 @@
import { memo, useEffect, useRef, useState } from 'react';
import { nanoid } from 'nanoid';
import { StyledBlockPreview } from '@toeverything/components/common';
import { services } from '@toeverything/datasource/db-service';
import { AsyncBlock } from '@toeverything/framework/virgo';
import { debounce, sleep } from '@toeverything/utils';
const updateTitle = async (
workspace: string,
blockId: string,
onFinal: (title?: string) => void,
retry = 0
) => {
const [page] = await services.api.editorBlock.search(workspace, {
tag: `id:${blockId}`,
});
if (page?.content) {
onFinal(page?.content);
} else if (retry < 20) {
await sleep(500);
updateTitle(workspace, blockId, onFinal, retry + 1);
} else {
onFinal('Untitled');
}
};
const bindBlock = async (
handleId: string,
workspace: string,
blockId: string,
onFinal: (title: string) => void,
retry = 0
): Promise<() => void> | undefined => {
const block = await services.api.editorBlock.getBlock(workspace, blockId);
if (block.id === blockId) {
const debouncedOnFinal = debounce(onFinal, 100, { maxWait: 500 });
const onUpdated = () =>
updateTitle(workspace, blockId, debouncedOnFinal);
block.on('content', handleId, onUpdated);
onUpdated();
return () => block.off('content', handleId);
} else if (retry < 20) {
await sleep(500);
return bindBlock(handleId, workspace, blockId, onFinal, retry + 1);
} else {
onFinal('Untitled');
return undefined;
}
};
const useBlockTitle = (block: AsyncBlock, blockId: string) => {
const [title, setTitle] = useState('Loading...');
useEffect(() => {
let callback: any = undefined;
bindBlock(
block.id + nanoid(8),
block.workspace,
blockId,
setTitle
).then(cb => {
callback = cb;
});
return () => callback?.();
}, [block.id, block.workspace, blockId]);
return title;
};
type BlockPreviewProps = {
block: AsyncBlock;
blockId: string;
editorElement?: () => JSX.Element;
};
const InternalBlockPreview = (props: BlockPreviewProps) => {
const container = useRef<HTMLDivElement>();
const [preview, setPreview] = useState(true);
const title = useBlockTitle(props.block, props.blockId);
const AffineEditor = props.editorElement as any;
useEffect(() => {
if (container?.current) {
const element = container?.current;
const resizeObserver = new IntersectionObserver(entries => {
const height = entries?.[0]?.intersectionRect.height;
setPreview(height < 174);
});
resizeObserver.observe(element);
return () => resizeObserver.unobserve(element);
}
return undefined;
}, [container, props]);
return (
<div ref={container}>
<StyledBlockPreview title={title}>
{preview ? (
<span
style={{
display: 'flex',
justifyContent: 'center',
fontSize: '128px',
height: '480px',
alignItems: 'center',
color: '#5591ff',
}}
>
Preview
</span>
) : AffineEditor ? (
<AffineEditor
workspace={props.block.workspace}
rootBlockId={props.blockId}
/>
) : null}
</StyledBlockPreview>
</div>
);
};
export const BlockPreview = memo(InternalBlockPreview, (prev, next) => {
return (
prev.block.workspace === next.block.workspace &&
prev.blockId === next.blockId
);
});

View File

@ -1,13 +1,11 @@
import { FC, memo, useEffect, useMemo, useRef, useState } from 'react';
import { FC } from 'react';
import { StyledBlockPreview } from '@toeverything/components/common';
import { styled } from '@toeverything/components/ui';
import { AsyncBlock, useRecastBlockScene } from '@toeverything/framework/virgo';
import { formatUrl } from './format-url';
import { SCENE_CONFIG } from '../../blocks/group/config';
import { services } from '@toeverything/datasource/db-service';
import { debounce } from '@toeverything/utils';
import { BlockPreview } from './BlockView';
const MouseMaskContainer = styled('div')({
position: 'absolute',
zIndex: 1,
@ -47,96 +45,6 @@ const _getLinkStyle = (scene: string) => {
}
};
type BlockPreviewProps = {
block: AsyncBlock;
blockId: string;
editorElement?: () => JSX.Element;
};
const BlockPreview = (props: BlockPreviewProps) => {
const container = useRef<HTMLDivElement>();
const [preview, setPreview] = useState(true);
const [title, setTitle] = useState('Loading...');
useEffect(() => {
let callback: any = undefined;
services.api.editorBlock
.getBlock(props.block.workspace, props.blockId)
.then(block => {
if (block.id === props.blockId) {
const updateTitle = debounce(
async () => {
const [page] =
await services.api.editorBlock.search(
props.block.workspace,
{ tag: 'id:affine67Uz4DstDk6PKUbz' }
);
console.log(page);
setTitle(page?.content || 'Untitled');
},
100,
{ maxWait: 500 }
);
block.on('content', props.block.id, updateTitle);
callback = () => block.off('content', props.block.id);
updateTitle();
} else {
setTitle('Untitled');
}
});
return () => callback?.();
}, [props.block.id, props.block.workspace, props.blockId]);
const AffineEditor = props.editorElement as any;
useEffect(() => {
if (container?.current) {
const element = container?.current;
const resizeObserver = new IntersectionObserver(entries => {
const height = entries?.[0]?.intersectionRect.height;
setPreview(height < 174);
});
resizeObserver.observe(element);
return () => resizeObserver.unobserve(element);
}
return undefined;
}, [container]);
return (
<div ref={container}>
<StyledBlockPreview title={title}>
{preview ? (
<span
style={{
display: 'flex',
justifyContent: 'center',
fontSize: '128px',
height: '480px',
alignItems: 'center',
color: '#5591ff',
}}
>
Preview
</span>
) : AffineEditor ? (
<AffineEditor
workspace={props.block.workspace}
rootBlockId={props.blockId}
/>
) : null}
</StyledBlockPreview>
</div>
);
};
const MemoBlockPreview = memo(BlockPreview, (prev, next) => {
return (
prev.block.workspace === next.block.workspace &&
prev.blockId === next.blockId
);
});
const SourceViewContainer = styled('div')<{
isSelected: boolean;
scene: string;
@ -186,7 +94,7 @@ export const SourceView: FC<Props> = props => {
scene={SCENE_CONFIG.REFLINK}
style={{ padding: '0' }}
>
<MemoBlockPreview
<BlockPreview
block={block}
editorElement={editorElement}
blockId={src}

View File

@ -78,6 +78,7 @@ const _useUserAndSpacesForFreeLogin = () => {
loading,
};
};
export const useUserAndSpaces = process.env['NX_LOCAL']
? _useUserAndSpacesForFreeLogin
: _useUserAndSpace;

View File

@ -4,7 +4,7 @@
"license": "MIT",
"author": "AFFiNE <developer@affine.pro>",
"scripts": {
"start": "env-cmd -f .env.local nx serve ligo-virgo",
"start": "env-cmd -f .env.local-dev nx serve ligo-virgo",
"start:affine": "nx serve ligo-virgo",
"start:keck": "nx serve keck",
"build": "nx build ligo-virgo",

View File

@ -379,6 +379,7 @@ importers:
code-example: ^3.3.6
codemirror: 6.0.1
keymap: link:@codemirror/next/keymap
nanoid: ^4.0.0
react-resizable: ^3.0.4
react-window: ^1.8.7
slate: ^0.81.1
@ -414,6 +415,7 @@ importers:
code-example: 3.3.6
codemirror: 6.0.1
keymap: link:@codemirror/next/keymap
nanoid: 4.0.0
react-resizable: 3.0.4
react-window: 1.8.7
slate: 0.81.1