Merge pull request #270 from toeverything/fix/whiteboard-edgeless

fix: whiteboard -> edgeless
This commit is contained in:
zuomeng wang
2022-08-16 21:02:28 +08:00
committed by GitHub
21 changed files with 53 additions and 67 deletions

View File

@@ -26,7 +26,7 @@ module.exports = {
], ],
scopes: [ scopes: [
{ name: 'selection' }, { name: 'selection' },
{ name: 'whiteboard' }, { name: 'edgeless' },
{ name: 'point' }, { name: 'point' },
{ name: 'group' }, { name: 'group' },
{ name: 'page' }, { name: 'page' },

View File

@@ -4,7 +4,7 @@ describe('ligo-virgo', () => {
beforeEach(() => cy.visit('/')); beforeEach(() => cy.visit('/'));
it('basic load check', () => { it('basic load check', () => {
getTitle().contains('👋 Get Started with AFFINE'); getTitle().contains('👋 Get Started with AFFiNE');
cy.get('.block_container').contains('The Essentials'); cy.get('.block_container').contains('The Essentials');

View File

@@ -9,11 +9,11 @@ const MemoAffineBoard = memo(AffineBoard, (prev, next) => {
return prev.rootBlockId === next.rootBlockId; return prev.rootBlockId === next.rootBlockId;
}); });
type WhiteboardProps = { type EdgelessProps = {
workspace: string; workspace: string;
}; };
export const Whiteboard = (props: WhiteboardProps) => { export const Edgeless = (props: EdgelessProps) => {
const { page_id } = useParams(); const { page_id } = useParams();
const { user } = useUserAndSpaces(); const { user } = useUserAndSpaces();

View File

@@ -22,7 +22,7 @@ export function WorkspaceHome() {
workspace_id, workspace_id,
user_initial_page_id, user_initial_page_id,
TemplateFactory.generatePageTemplateByGroupKeys({ TemplateFactory.generatePageTemplateByGroupKeys({
name: '👋 Get Started with AFFINE', name: '👋 Get Started with AFFiNE',
groupKeys: [ groupKeys: [
'getStartedGroup0', 'getStartedGroup0',
'getStartedGroup1', 'getStartedGroup1',

View File

@@ -4,10 +4,10 @@ import { useUserAndSpaces } from '@toeverything/datasource/state';
import { WorkspaceRootContainer } from './Container'; import { WorkspaceRootContainer } from './Container';
import { Page } from './docs'; import { Page } from './docs';
import { Edgeless } from './Edgeless';
import { WorkspaceHome } from './Home'; import { WorkspaceHome } from './Home';
import Labels from './labels'; import Labels from './labels';
import Pages from './pages'; import Pages from './pages';
import { Whiteboard } from './Whiteboard';
export function WorkspaceContainer() { export function WorkspaceContainer() {
const { workspace_id } = useParams(); const { workspace_id } = useParams();
@@ -26,8 +26,8 @@ export function WorkspaceContainer() {
<Route path="/labels" element={<Labels />} /> <Route path="/labels" element={<Labels />} />
<Route path="/pages" element={<Pages />} /> <Route path="/pages" element={<Pages />} />
<Route <Route
path="/:page_id/whiteboard" path="/:page_id/edgeless"
element={<Whiteboard workspace={workspace_id} />} element={<Edgeless workspace={workspace_id} />}
/> />
<Route <Route
path="/:page_id" path="/:page_id"

View File

@@ -73,9 +73,9 @@ module.exports = function (webpackConfig) {
priority: -5, priority: -5,
chunks: 'all', chunks: 'all',
}, },
whiteboard: { edgeless: {
test: /(libs\/components\/board-|[\\/]node_modules[\\/]@tldraw)/, test: /(libs\/components\/board-|[\\/]node_modules[\\/]@tldraw)/,
name: 'whiteboard', name: 'edgeless',
priority: -7, priority: -7,
chunks: 'all', chunks: 'all',
}, },

View File

@@ -17,7 +17,7 @@ interface AffineEditorProps {
*/ */
scrollBlank?: boolean; scrollBlank?: boolean;
isWhiteboard?: boolean; isEdgeless?: boolean;
scrollContainer?: HTMLElement; scrollContainer?: HTMLElement;
scrollController?: { scrollController?: {
@@ -29,12 +29,12 @@ interface AffineEditorProps {
function _useConstantWithDispose( function _useConstantWithDispose(
workspace: string, workspace: string,
rootBlockId: string, rootBlockId: string,
isWhiteboard: boolean isEdgeless: boolean
) { ) {
const ref = useRef<{ data: BlockEditor; onInit: boolean }>(null); const ref = useRef<{ data: BlockEditor; onInit: boolean }>(null);
const { setCurrentEditors } = useCurrentEditors(); const { setCurrentEditors } = useCurrentEditors();
ref.current ??= { ref.current ??= {
data: createEditor(workspace, rootBlockId, isWhiteboard), data: createEditor(workspace, rootBlockId, isEdgeless),
onInit: true, onInit: true,
}; };
@@ -42,18 +42,14 @@ function _useConstantWithDispose(
if (ref.current.onInit) { if (ref.current.onInit) {
ref.current.onInit = false; ref.current.onInit = false;
} else { } else {
ref.current.data = createEditor( ref.current.data = createEditor(workspace, rootBlockId, isEdgeless);
workspace,
rootBlockId,
isWhiteboard
);
} }
setCurrentEditors(prev => ({ setCurrentEditors(prev => ({
...prev, ...prev,
[rootBlockId]: ref.current.data, [rootBlockId]: ref.current.data,
})); }));
return () => ref.current.data.dispose(); return () => ref.current.data.dispose();
}, [workspace, rootBlockId, isWhiteboard, setCurrentEditors]); }, [workspace, rootBlockId, isEdgeless, setCurrentEditors]);
return ref.current.data; return ref.current.data;
} }
@@ -64,7 +60,7 @@ export const AffineEditor = forwardRef<BlockEditor, AffineEditorProps>(
workspace, workspace,
rootBlockId, rootBlockId,
scrollBlank = true, scrollBlank = true,
isWhiteboard, isEdgeless,
scrollController, scrollController,
scrollContainer, scrollContainer,
}, },
@@ -73,7 +69,7 @@ export const AffineEditor = forwardRef<BlockEditor, AffineEditorProps>(
const editor = _useConstantWithDispose( const editor = _useConstantWithDispose(
workspace, workspace,
rootBlockId, rootBlockId,
isWhiteboard isEdgeless
); );
useEffect(() => { useEffect(() => {

View File

@@ -30,7 +30,7 @@ import { BlockEditor } from '@toeverything/framework/virgo';
export const createEditor = ( export const createEditor = (
workspace: string, workspace: string,
rootBlockId: string, rootBlockId: string,
isWhiteboard?: boolean isEdgeless?: boolean
) => { ) => {
const blockEditor = new BlockEditor({ const blockEditor = new BlockEditor({
workspace, workspace,
@@ -61,7 +61,7 @@ export const createEditor = (
[Protocol.Block.Type.groupDivider]: new GroupDividerBlock(), [Protocol.Block.Type.groupDivider]: new GroupDividerBlock(),
}, },
plugins, plugins,
isWhiteboard, isEdgeless,
}); });
return blockEditor; return blockEditor;

View File

@@ -148,7 +148,7 @@ export class EditorUtil extends TDShapeUtil<T, E> {
workspace={workspace} workspace={workspace}
rootBlockId={rootBlockId} rootBlockId={rootBlockId}
scrollBlank={false} scrollBlank={false}
isWhiteboard isEdgeless
/> />
{editingText ? null : <Mask />} {editingText ? null : <Mask />}
</Container> </Container>

View File

@@ -103,7 +103,7 @@ export const GroupView = (props: CreateView) => {
<View {...props} /> <View {...props} />
</GroupContainer> </GroupContainer>
{editor.isWhiteboard ? null : ( {editor.isEdgeless ? null : (
<GroupAction onAddGroup={addGroup} /> <GroupAction onAddGroup={addGroup} />
)} )}
</GroupBox> </GroupBox>

View File

@@ -1,5 +1,5 @@
const _regex = const _regex =
/^(https?:\/\/(localhost:4200|(nightly|app)\.affine\.pro|.*?\.ligo-virgo\.pages\.dev)\/\w{28}\/)?(affine\w{16})(\/whiteboard)?$/; /^(https?:\/\/(localhost:4200|(nightly|app)\.affine\.pro|.*?\.ligo-virgo\.pages\.dev)\/\w{28}\/)?(affine\w{16})(\/edgeless)?$/;
export const isAffineUrl = (url?: string) => { export const isAffineUrl = (url?: string) => {
if (!url) return false; if (!url) return false;

View File

@@ -1,16 +1,16 @@
import type { BlockEditor } from './editor';
import { styled, usePatchNodes } from '@toeverything/components/ui'; import { styled, usePatchNodes } from '@toeverything/components/ui';
import type { PropsWithChildren } from 'react';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { EditorProvider } from './Contexts';
import { SelectionRect, SelectionRef } from './Selection';
import { import {
Protocol, Protocol,
services, services,
type ReturnUnobserve, type ReturnUnobserve,
} from '@toeverything/datasource/db-service'; } from '@toeverything/datasource/db-service';
import { addNewGroup, appendNewGroup } from './recast-block'; import type { PropsWithChildren } from 'react';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import { EditorProvider } from './Contexts';
import type { BlockEditor } from './editor';
import { useIsOnDrag } from './hooks'; import { useIsOnDrag } from './hooks';
import { addNewGroup, appendNewGroup } from './recast-block';
import { SelectionRect, SelectionRef } from './Selection';
interface RenderRootProps { interface RenderRootProps {
editor: BlockEditor; editor: BlockEditor;
@@ -160,7 +160,7 @@ export const RenderRoot = ({
return ( return (
<EditorProvider value={{ editor, editorElement }}> <EditorProvider value={{ editor, editorElement }}>
<Container <Container
isWhiteboard={editor.isWhiteboard} isEdgeless={editor.isEdgeless}
ref={ref => { ref={ref => {
if (ref != null && ref !== editor.container) { if (ref != null && ref !== editor.container) {
editor.container = ref; editor.container = ref;
@@ -188,7 +188,7 @@ export const RenderRoot = ({
</Content> </Content>
{/** TODO: remove selectionManager insert */} {/** TODO: remove selectionManager insert */}
{editor && <SelectionRect ref={selectionRef} editor={editor} />} {editor && <SelectionRect ref={selectionRef} editor={editor} />}
{editor.isWhiteboard ? null : <ScrollBlank editor={editor} />} {editor.isEdgeless ? null : <ScrollBlank editor={editor} />}
{patchedNodes} {patchedNodes}
</Container> </Container>
</EditorProvider> </EditorProvider>
@@ -262,16 +262,10 @@ function ScrollBlank({ editor }: { editor: BlockEditor }) {
const PADDING_X = 150; const PADDING_X = 150;
const Container = styled('div')( const Container = styled('div')(
({ ({ isEdgeless, isOnDrag }: { isEdgeless: boolean; isOnDrag: boolean }) => ({
isWhiteboard,
isOnDrag,
}: {
isWhiteboard: boolean;
isOnDrag: boolean;
}) => ({
width: '100%', width: '100%',
padding: isWhiteboard ? 0 : `72px ${PADDING_X}px 0 ${PADDING_X}px`, padding: isEdgeless ? 0 : `72px ${PADDING_X}px 0 ${PADDING_X}px`,
minWidth: isWhiteboard ? 'unset' : '940px', minWidth: isEdgeless ? 'unset' : '940px',
position: 'relative', position: 'relative',
...(isOnDrag && { ...(isOnDrag && {
cursor: 'grabbing', cursor: 'grabbing',

View File

@@ -42,7 +42,7 @@ export interface EditorCtorProps {
views: Partial<Record<keyof BlockFlavors, BaseView>>; views: Partial<Record<keyof BlockFlavors, BaseView>>;
plugins: PluginCreator[]; plugins: PluginCreator[];
rootBlockId: string; rootBlockId: string;
isWhiteboard?: boolean; isEdgeless?: boolean;
} }
export class Editor implements Virgo { export class Editor implements Virgo {
@@ -75,7 +75,7 @@ export class Editor implements Virgo {
render: PatchNode; render: PatchNode;
has: (key: string) => boolean; has: (key: string) => boolean;
}; };
public isWhiteboard = false; public isEdgeless = false;
private _isDisposed = false; private _isDisposed = false;
constructor(props: EditorCtorProps) { constructor(props: EditorCtorProps) {
@@ -85,8 +85,8 @@ export class Editor implements Virgo {
this.hooks = new Hooks(); this.hooks = new Hooks();
this.plugin_manager = new PluginManager(this, this.hooks); this.plugin_manager = new PluginManager(this, this.hooks);
this.plugin_manager.registerAll(props.plugins); this.plugin_manager.registerAll(props.plugins);
if (props.isWhiteboard) { if (props.isEdgeless) {
this.isWhiteboard = true; this.isEdgeless = true;
} }
for (const [name, block] of Object.entries(props.views)) { for (const [name, block] of Object.entries(props.views)) {
services.api.editorBlock.registerContentExporter( services.api.editorBlock.registerContentExporter(

View File

@@ -107,7 +107,7 @@ export interface Virgo {
getBlockDomById: (id: string) => Promise<HTMLElement>; getBlockDomById: (id: string) => Promise<HTMLElement>;
getBlockByPoint: (point: Point) => Promise<AsyncBlock>; getBlockByPoint: (point: Point) => Promise<AsyncBlock>;
getGroupBlockByPoint: (point: Point) => Promise<AsyncBlock>; getGroupBlockByPoint: (point: Point) => Promise<AsyncBlock>;
isWhiteboard: boolean; isEdgeless: boolean;
mouseManager: MouseManager; mouseManager: MouseManager;
} }

View File

@@ -7,7 +7,6 @@ export enum RecastScene {
Page = 'page', Page = 'page',
Kanban = 'kanban', Kanban = 'kanban',
Table = 'table', Table = 'table',
// Whiteboard = 'whiteboard',
} }
export type RecastViewId = string & { export type RecastViewId = string & {

View File

@@ -14,7 +14,7 @@ export class GroupMenuPlugin extends BasePlugin {
} }
protected override _onRender(): void { protected override _onRender(): void {
if (this.editor.isWhiteboard) return; if (this.editor.isEdgeless) return;
this.root = new PluginRenderRoot({ this.root = new PluginRenderRoot({
name: PLUGIN_NAME, name: PLUGIN_NAME,
render: this.editor.reactRenderRoot.render, render: this.editor.reactRenderRoot.render,

View File

@@ -4,7 +4,7 @@ import { StatusText } from './StatusText';
import { StatusTrack } from './StatusTrack'; import { StatusTrack } from './StatusTrack';
import { DocMode } from './type'; import { DocMode } from './type';
const isBoard = (pathname: string): boolean => pathname.endsWith('/whiteboard'); const isBoard = (pathname: string): boolean => pathname.endsWith('/edgeless');
export const Switcher = () => { export const Switcher = () => {
const navigate = useNavigate(); const navigate = useNavigate();
@@ -20,11 +20,11 @@ export const Switcher = () => {
/** /**
* There are two possible modes: * There are two possible modes:
* Page mode: /{workspaceId}/{pageId} * Page mode: /{workspaceId}/{pageId}
* Board mode: /{workspaceId}/{pageId}/whiteboard * Board mode: /{workspaceId}/{pageId}/edgeless
*/ */
const pageId = params['*'].split('/')[0]; const pageId = params['*'].split('/')[0];
const targetUrl = `/${workspaceId}/${pageId}${ const targetUrl = `/${workspaceId}/${pageId}${
targetViewMode === DocMode.board ? '/whiteboard' : '' targetViewMode === DocMode.board ? '/edgeless' : ''
}`; }`;
navigate(targetUrl); navigate(targetUrl);
}; };

View File

@@ -26,7 +26,7 @@ function hideAffineHeader(pathname: string): boolean {
} }
type HeaderIconProps = { type HeaderIconProps = {
isWhiteboardView?: boolean; isEdgelessView?: boolean;
}; };
export const AffineHeader = () => { export const AffineHeader = () => {
@@ -38,7 +38,7 @@ export const AffineHeader = () => {
const { toggleSettingsSidebar: toggleInfoSidebar } = const { toggleSettingsSidebar: toggleInfoSidebar } =
useShowSettingsSidebar(); useShowSettingsSidebar();
const theme = useTheme(); const theme = useTheme();
const isWhiteboardView = pathname.endsWith('/whiteboard'); const isEdgelessView = pathname.endsWith('/edgeless');
const pageHistoryPortalFlag = useFlag('BooleanPageHistoryPortal', false); const pageHistoryPortalFlag = useFlag('BooleanPageHistoryPortal', false);
const pageSettingPortalFlag = useFlag('PageSettingPortal', false); const pageSettingPortalFlag = useFlag('PageSettingPortal', false);
const BooleanPageSharePortal = useFlag('BooleanPageSharePortal', false); const BooleanPageSharePortal = useFlag('BooleanPageSharePortal', false);
@@ -77,9 +77,9 @@ export const AffineHeader = () => {
<Tooltip content="Doc"> <Tooltip content="Doc">
<HeaderIcon <HeaderIcon
style={{ width: '80px' }} style={{ width: '80px' }}
isWhiteboardView={!isWhiteboardView} isEdgelessView={!isEdgelessView}
onClick={() => onClick={() =>
isWhiteboardView isEdgelessView
? navigate( ? navigate(
`/${ `/${
params['workspace_id'] || params['workspace_id'] ||
@@ -100,17 +100,17 @@ export const AffineHeader = () => {
</span> </span>
</HeaderIcon> </HeaderIcon>
</Tooltip> </Tooltip>
<Tooltip content="Whiteboard"> <Tooltip content="Edgeless">
<HeaderIcon <HeaderIcon
isWhiteboardView={isWhiteboardView} isEdgelessView={isEdgelessView}
onClick={() => onClick={() =>
isWhiteboardView isEdgelessView
? null ? null
: navigate( : navigate(
`/${ `/${
params['workspace_id'] || params['workspace_id'] ||
'space' 'space'
}/${params['*']}` + '/whiteboard' }/${params['*']}` + '/edgeless'
) )
} }
> >
@@ -166,14 +166,14 @@ const StyledHeaderRight = styled('div')`
`; `;
const HeaderIcon = styled(IconButton, { const HeaderIcon = styled(IconButton, {
shouldForwardProp: (prop: string) => prop !== 'isWhiteboardView', shouldForwardProp: (prop: string) => prop !== 'isEdgelessView',
})<HeaderIconProps>(({ isWhiteboardView = false }) => ({ })<HeaderIconProps>(({ isEdgelessView = false }) => ({
color: '#98ACBD', color: '#98ACBD',
minWidth: 48, minWidth: 48,
width: 48, width: 48,
height: 36, height: 36,
borderRadius: '8px', borderRadius: '8px',
...(isWhiteboardView && { ...(isEdgelessView && {
color: '#fff', color: '#fff',
backgroundColor: '#3E6FDB', backgroundColor: '#3E6FDB',
'&:hover': { '&:hover': {

View File

@@ -22,7 +22,6 @@ const Protocol = {
quote: 'quote', quote: 'quote',
toc: 'toc', toc: 'toc',
database: 'database', database: 'database',
whiteboard: 'whiteboard',
template: 'template', template: 'template',
discussion: 'discussion', discussion: 'discussion',
comment: 'comment', comment: 'comment',

View File

@@ -16,7 +16,6 @@ export enum GroupScene {
page = 'page', page = 'page',
table = 'table', table = 'table',
kanban = 'kanban', kanban = 'kanban',
whiteboard = 'whiteboard',
} }
/** /**

View File

@@ -37,7 +37,6 @@ export const BlockFlavors = {
quote: 'quote' as const, // quote quote: 'quote' as const, // quote
toc: 'toc' as const, //directory toc: 'toc' as const, //directory
database: 'database' as const, //Multidimensional table database: 'database' as const, //Multidimensional table
whiteboard: 'whiteboard' as const, // whiteboard
template: 'template' as const, // template template: 'template' as const, // template
discussion: 'discussion' as const, // comment header discussion: 'discussion' as const, // comment header
comment: 'comment' as const, // comment details comment: 'comment' as const, // comment details