mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-09 21:25:45 +08:00
feat: init support for multiple tiles (#2585)
This commit is contained in:
@@ -45,6 +45,7 @@
|
|||||||
"react": "18.3.0-canary-16d053d59-20230506",
|
"react": "18.3.0-canary-16d053d59-20230506",
|
||||||
"react-dom": "18.3.0-canary-16d053d59-20230506",
|
"react-dom": "18.3.0-canary-16d053d59-20230506",
|
||||||
"react-is": "^18.2.0",
|
"react-is": "^18.2.0",
|
||||||
|
"react-mosaic-component": "^6.0.1",
|
||||||
"rxjs": "^7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"swr": "^2.1.5",
|
"swr": "^2.1.5",
|
||||||
"y-protocols": "^1.0.5",
|
"y-protocols": "^1.0.5",
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import { globalStyle } from '@vanilla-extract/css';
|
||||||
|
|
||||||
|
globalStyle('.mosaic.mosaic-blueprint-theme', {
|
||||||
|
backgroundColor: 'var(--background-color)',
|
||||||
|
});
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
import { PageNotFoundError } from '@affine/env/constant';
|
import './page-detail-editor.css';
|
||||||
|
|
||||||
|
import { PageNotFoundError, Unreachable } from '@affine/env/constant';
|
||||||
import type { EditorContainer } from '@blocksuite/editor';
|
import type { EditorContainer } from '@blocksuite/editor';
|
||||||
import type { Page } from '@blocksuite/store';
|
import type { Page } from '@blocksuite/store';
|
||||||
import { assertExists } from '@blocksuite/store';
|
import { assertExists } from '@blocksuite/store';
|
||||||
@@ -8,12 +10,18 @@ import { useBlockSuiteWorkspacePageTitle } from '@toeverything/hooks/use-block-s
|
|||||||
import { useAtomValue, useSetAtom } from 'jotai';
|
import { useAtomValue, useSetAtom } from 'jotai';
|
||||||
import Head from 'next/head';
|
import Head from 'next/head';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { startTransition, useCallback } from 'react';
|
import { lazy, memo, startTransition, useCallback } from 'react';
|
||||||
|
|
||||||
import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms';
|
import { currentEditorAtom, workspacePreferredModeAtom } from '../atoms';
|
||||||
import type { AffineOfficialWorkspace } from '../shared';
|
import type { AffineOfficialWorkspace } from '../shared';
|
||||||
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
|
import { BlockSuiteEditor as Editor } from './blocksuite/block-suite-editor';
|
||||||
|
|
||||||
|
const Mosaic = lazy(() =>
|
||||||
|
import('react-mosaic-component').then(({ Mosaic }) => ({
|
||||||
|
default: Mosaic,
|
||||||
|
}))
|
||||||
|
);
|
||||||
|
|
||||||
export type PageDetailEditorProps = {
|
export type PageDetailEditorProps = {
|
||||||
isPublic?: boolean;
|
isPublic?: boolean;
|
||||||
workspace: AffineOfficialWorkspace;
|
workspace: AffineOfficialWorkspace;
|
||||||
@@ -22,19 +30,18 @@ export type PageDetailEditorProps = {
|
|||||||
onLoad?: (page: Page, editor: EditorContainer) => () => void;
|
onLoad?: (page: Page, editor: EditorContainer) => () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
|
const EditorWrapper = memo(function EditorWrapper({
|
||||||
workspace,
|
workspace,
|
||||||
pageId,
|
pageId,
|
||||||
onInit,
|
onInit,
|
||||||
onLoad,
|
onLoad,
|
||||||
isPublic,
|
isPublic,
|
||||||
}) => {
|
}: PageDetailEditorProps) {
|
||||||
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||||
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
||||||
if (!page) {
|
if (!page) {
|
||||||
throw new PageNotFoundError(blockSuiteWorkspace, pageId);
|
throw new PageNotFoundError(blockSuiteWorkspace, pageId);
|
||||||
}
|
}
|
||||||
const title = useBlockSuiteWorkspacePageTitle(blockSuiteWorkspace, pageId);
|
|
||||||
const meta = useBlockSuitePageMeta(blockSuiteWorkspace).find(
|
const meta = useBlockSuitePageMeta(blockSuiteWorkspace).find(
|
||||||
meta => meta.id === pageId
|
meta => meta.id === pageId
|
||||||
);
|
);
|
||||||
@@ -42,43 +49,67 @@ export const PageDetailEditor: React.FC<PageDetailEditorProps> = ({
|
|||||||
useAtomValue(workspacePreferredModeAtom)[pageId] ?? 'page';
|
useAtomValue(workspacePreferredModeAtom)[pageId] ?? 'page';
|
||||||
const setEditor = useSetAtom(currentEditorAtom);
|
const setEditor = useSetAtom(currentEditorAtom);
|
||||||
assertExists(meta);
|
assertExists(meta);
|
||||||
|
return (
|
||||||
|
<Editor
|
||||||
|
style={{
|
||||||
|
height: 'calc(100% - 52px)',
|
||||||
|
}}
|
||||||
|
key={`${workspace.flavour}-${workspace.id}-${pageId}`}
|
||||||
|
mode={isPublic ? 'page' : currentMode}
|
||||||
|
page={page}
|
||||||
|
onInit={useCallback(
|
||||||
|
(page: Page, editor: Readonly<EditorContainer>) => {
|
||||||
|
startTransition(() => {
|
||||||
|
setEditor(editor);
|
||||||
|
});
|
||||||
|
onInit(page, editor);
|
||||||
|
},
|
||||||
|
[onInit, setEditor]
|
||||||
|
)}
|
||||||
|
onLoad={useCallback(
|
||||||
|
(page: Page, editor: EditorContainer) => {
|
||||||
|
startTransition(() => {
|
||||||
|
setEditor(editor);
|
||||||
|
});
|
||||||
|
page.workspace.setPageMeta(page.id, {
|
||||||
|
updatedDate: Date.now(),
|
||||||
|
});
|
||||||
|
localStorage.setItem('last_page_id', page.id);
|
||||||
|
if (onLoad) {
|
||||||
|
return onLoad(page, editor);
|
||||||
|
}
|
||||||
|
return () => {};
|
||||||
|
},
|
||||||
|
[onLoad, setEditor]
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const PageDetailEditor: React.FC<PageDetailEditorProps> = props => {
|
||||||
|
const { workspace, pageId } = props;
|
||||||
|
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
|
||||||
|
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
||||||
|
if (!page) {
|
||||||
|
throw new PageNotFoundError(blockSuiteWorkspace, pageId);
|
||||||
|
}
|
||||||
|
const title = useBlockSuiteWorkspacePageTitle(blockSuiteWorkspace, pageId);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
</Head>
|
</Head>
|
||||||
<Editor
|
<Mosaic
|
||||||
style={{
|
onChange={useCallback(() => {}, [])}
|
||||||
height: 'calc(100% - 52px)',
|
renderTile={id => {
|
||||||
|
if (id === 'editor') {
|
||||||
|
return <EditorWrapper {...props} />;
|
||||||
|
} else {
|
||||||
|
// @affine/copilot and other plugins will be added in the future
|
||||||
|
throw new Unreachable();
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
key={`${workspace.flavour}-${workspace.id}-${pageId}`}
|
value="editor"
|
||||||
mode={isPublic ? 'page' : currentMode}
|
|
||||||
page={page}
|
|
||||||
onInit={useCallback(
|
|
||||||
(page: Page, editor: Readonly<EditorContainer>) => {
|
|
||||||
startTransition(() => {
|
|
||||||
setEditor(editor);
|
|
||||||
});
|
|
||||||
onInit(page, editor);
|
|
||||||
},
|
|
||||||
[onInit, setEditor]
|
|
||||||
)}
|
|
||||||
onLoad={useCallback(
|
|
||||||
(page: Page, editor: EditorContainer) => {
|
|
||||||
startTransition(() => {
|
|
||||||
setEditor(editor);
|
|
||||||
});
|
|
||||||
page.workspace.setPageMeta(page.id, {
|
|
||||||
updatedDate: Date.now(),
|
|
||||||
});
|
|
||||||
localStorage.setItem('last_page_id', page.id);
|
|
||||||
if (onLoad) {
|
|
||||||
return onLoad(page, editor);
|
|
||||||
}
|
|
||||||
return () => {};
|
|
||||||
},
|
|
||||||
[onLoad, setEditor]
|
|
||||||
)}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import '@affine/component/theme/global.css';
|
import '@affine/component/theme/global.css';
|
||||||
import '@affine/component/theme/theme.css';
|
import '@affine/component/theme/theme.css';
|
||||||
|
import 'react-mosaic-component/react-mosaic-component.css';
|
||||||
|
|
||||||
import { WorkspaceFallback } from '@affine/component/workspace';
|
import { WorkspaceFallback } from '@affine/component/workspace';
|
||||||
import { config, setupGlobal } from '@affine/env';
|
import { config, setupGlobal } from '@affine/env';
|
||||||
|
|||||||
@@ -360,6 +360,7 @@ __metadata:
|
|||||||
react: 18.3.0-canary-16d053d59-20230506
|
react: 18.3.0-canary-16d053d59-20230506
|
||||||
react-dom: 18.3.0-canary-16d053d59-20230506
|
react-dom: 18.3.0-canary-16d053d59-20230506
|
||||||
react-is: ^18.2.0
|
react-is: ^18.2.0
|
||||||
|
react-mosaic-component: ^6.0.1
|
||||||
redux: ^4.2.1
|
redux: ^4.2.1
|
||||||
rxjs: ^7.8.1
|
rxjs: ^7.8.1
|
||||||
swc-plugin-coverage-instrument: ^0.0.18
|
swc-plugin-coverage-instrument: ^0.0.18
|
||||||
@@ -12433,6 +12434,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"classnames@npm:^2.3.2":
|
||||||
|
version: 2.3.2
|
||||||
|
resolution: "classnames@npm:2.3.2"
|
||||||
|
checksum: 2c62199789618d95545c872787137262e741f9db13328e216b093eea91c85ef2bfb152c1f9e63027204e2559a006a92eb74147d46c800a9f96297ae1d9f96f4e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"clean-regexp@npm:^1.0.0":
|
"clean-regexp@npm:^1.0.0":
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
resolution: "clean-regexp@npm:1.0.0"
|
resolution: "clean-regexp@npm:1.0.0"
|
||||||
@@ -13956,6 +13964,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"dnd-multi-backend@npm:^8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "dnd-multi-backend@npm:8.0.0"
|
||||||
|
checksum: ce19b14c509e3740f6ab8cab725f8df2e7ad79fd04cb7d57d4b3f9e579cd5ab1f9439517b4325e014ca1caeab6152adced993085b734aff5a5d40cbb766a5da0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"doctrine@npm:^2.1.0":
|
"doctrine@npm:^2.1.0":
|
||||||
version: 2.1.0
|
version: 2.1.0
|
||||||
resolution: "doctrine@npm:2.1.0"
|
resolution: "doctrine@npm:2.1.0"
|
||||||
@@ -17545,6 +17560,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"immutability-helper@npm:^3.1.1":
|
||||||
|
version: 3.1.1
|
||||||
|
resolution: "immutability-helper@npm:3.1.1"
|
||||||
|
checksum: 6fdbf6d2123efa567263e904bbaff07aca0e24560d270d34967b03aab8ec20bd3e4057f394d59e50eb6c4718c9415591a6281692bb0aafd522ad72cf4887133f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"immutable@npm:^4.2.2":
|
"immutable@npm:^4.2.2":
|
||||||
version: 4.3.0
|
version: 4.3.0
|
||||||
resolution: "immutable@npm:4.3.0"
|
resolution: "immutable@npm:4.3.0"
|
||||||
@@ -23073,6 +23095,17 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"rdndmb-html5-to-touch@npm:^8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "rdndmb-html5-to-touch@npm:8.0.0"
|
||||||
|
dependencies:
|
||||||
|
dnd-multi-backend: ^8.0.0
|
||||||
|
react-dnd-html5-backend: ^16.0.1
|
||||||
|
react-dnd-touch-backend: ^16.0.1
|
||||||
|
checksum: 9ede5db33820ca592f0c0aaed3b9a6cd9026cd7ffe60c2cdabd62275ab253b3a69db2b4eb909c250602b98d413bf635380ba6d5df574ca002d076fdc12f94606
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-base16-styling@npm:^0.9.1":
|
"react-base16-styling@npm:^0.9.1":
|
||||||
version: 0.9.1
|
version: 0.9.1
|
||||||
resolution: "react-base16-styling@npm:0.9.1"
|
resolution: "react-base16-styling@npm:0.9.1"
|
||||||
@@ -23098,7 +23131,49 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-dnd@npm:*":
|
"react-dnd-html5-backend@npm:^16.0.1":
|
||||||
|
version: 16.0.1
|
||||||
|
resolution: "react-dnd-html5-backend@npm:16.0.1"
|
||||||
|
dependencies:
|
||||||
|
dnd-core: ^16.0.1
|
||||||
|
checksum: e2368bf85d5632a5cd867b743feb54c9052d909ea5331608860fa455edf3c633ac791f5b338e3db29b19ea8670c0ba5fb43c9c1c2510760bea030811d726cdfa
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"react-dnd-multi-backend@npm:^8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "react-dnd-multi-backend@npm:8.0.0"
|
||||||
|
dependencies:
|
||||||
|
dnd-multi-backend: ^8.0.0
|
||||||
|
react-dnd-preview: ^8.0.0
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.14.0 || ^17.0.2 || ^18.0.0
|
||||||
|
react-dom: ^16.14.0 || ^17.0.2 || ^18.0.0
|
||||||
|
checksum: a0871a4845df814f3a57b5c110e1601439d74d6433d2115a2078a4d49a200aa33a91b37a23d6dafaebc2ab857a25caa7d83d28cee034aa6907f7224c6257e56f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"react-dnd-preview@npm:^8.0.0":
|
||||||
|
version: 8.0.0
|
||||||
|
resolution: "react-dnd-preview@npm:8.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
react: ^16.14.0 || ^17.0.2 || ^18.0.0
|
||||||
|
react-dnd: ^16.0.1
|
||||||
|
checksum: abed644a2ccd454a8fc54fa5bc4904beeb8ccf40c1ea20fb3c5ff178733062fd9f5d657435fb671c5736c93d9e7b2ce8e7de8c07cbc9822b459f02fdbfc99b77
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"react-dnd-touch-backend@npm:^16.0.1":
|
||||||
|
version: 16.0.1
|
||||||
|
resolution: "react-dnd-touch-backend@npm:16.0.1"
|
||||||
|
dependencies:
|
||||||
|
"@react-dnd/invariant": ^4.0.1
|
||||||
|
dnd-core: ^16.0.1
|
||||||
|
checksum: 5362c5f4266e3655d02c716f341dc55c61fae53e12eb3b239245bafb7a3f3cdb953e27e187e8dcb9d86c01bc738853d764d7c85b87104a49a8a8f1ecc4d35755
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"react-dnd@npm:*, react-dnd@npm:^16.0.1":
|
||||||
version: 16.0.1
|
version: 16.0.1
|
||||||
resolution: "react-dnd@npm:16.0.1"
|
resolution: "react-dnd@npm:16.0.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -23269,6 +23344,26 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"react-mosaic-component@npm:^6.0.1":
|
||||||
|
version: 6.0.1
|
||||||
|
resolution: "react-mosaic-component@npm:6.0.1"
|
||||||
|
dependencies:
|
||||||
|
classnames: ^2.3.2
|
||||||
|
immutability-helper: ^3.1.1
|
||||||
|
lodash: ^4.17.21
|
||||||
|
prop-types: ^15.8.1
|
||||||
|
rdndmb-html5-to-touch: ^8.0.0
|
||||||
|
react-dnd: ^16.0.1
|
||||||
|
react-dnd-html5-backend: ^16.0.1
|
||||||
|
react-dnd-multi-backend: ^8.0.0
|
||||||
|
react-dnd-touch-backend: ^16.0.1
|
||||||
|
uuid: ^9.0.0
|
||||||
|
peerDependencies:
|
||||||
|
react: 16 - 18
|
||||||
|
checksum: fb31b655fd841d09a5ca922f391c29cad8c7b0e87ac5d84386a434cb7d01f5a633f116b8c7ef4b79203cf0b1768a43c27ba65d41f22feba46a141be366b31de2
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"react-refresh@npm:^0.14.0":
|
"react-refresh@npm:^0.14.0":
|
||||||
version: 0.14.0
|
version: 0.14.0
|
||||||
resolution: "react-refresh@npm:0.14.0"
|
resolution: "react-refresh@npm:0.14.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user