feat: modify blocksuite

This commit is contained in:
QiShaoXuan
2022-12-09 01:37:32 +08:00
parent 8885cd0ba2
commit 6e327900f1
7 changed files with 225 additions and 84 deletions
+3 -3
View File
@@ -9,10 +9,10 @@
"lint": "next lint"
},
"dependencies": {
"@blocksuite/blocks": "0.3.0-alpha.5",
"@blocksuite/editor": "0.3.0-alpha.5",
"@blocksuite/blocks": "0.3.0-alpha.6",
"@blocksuite/editor": "0.3.0-alpha.6",
"@blocksuite/icons": "^1.0.5",
"@blocksuite/store": "0.3.0-alpha.5",
"@blocksuite/store": "0.3.0-alpha.6",
"@emotion/css": "^11.10.0",
"@emotion/react": "^11.10.4",
"@emotion/server": "^11.10.0",
+1 -1
View File
@@ -12,7 +12,7 @@ export const Editor = () => {
editorContainer.current?.appendChild(editor);
initDefaultContent(editor);
// initDefaultContent(editor);
}
}, [editor]);
@@ -9,8 +9,10 @@ import {
} from './style';
import { Arrow } from './icons';
import Link from 'next/link';
import { useEditor } from '@/providers/editor-provider';
export const WorkSpaceSliderBar = () => {
const [show, setShow] = useState(false);
const { createPage } = useEditor();
const router = useRouter();
return (
<>
@@ -29,11 +31,9 @@ export const WorkSpaceSliderBar = () => {
>
Back to Doc
</StyledListItem>
<StyledListItem>
<Link href={{ pathname: '/all-page', query: { name: 'test' } }}>
All pages
</Link>
</StyledListItem>
<Link href={{ pathname: '/all-page', query: { name: 'test' } }}>
<StyledListItem>All pages</StyledListItem>
</Link>
<StyledListItem>Favourites</StyledListItem>
<StyledSubListItem>
document 1, this is a paper icondocument 1
@@ -43,7 +43,13 @@ export const WorkSpaceSliderBar = () => {
<StyledListItem>Import</StyledListItem>
<StyledListItem>Bin</StyledListItem>
<StyledNewPageButton>New Page</StyledNewPageButton>
<StyledNewPageButton
onClick={() => {
createPage();
}}
>
New Page
</StyledNewPageButton>
</StyledSliderBar>
<StyledArrowButton
isShow={show}
+107 -24
View File
@@ -1,11 +1,18 @@
import React from 'react';
import { Header } from '@/components/header';
import { styled } from '@/styles';
import { displayFlex, styled, textEllipsis } from '@/styles';
import { Table, TableCell, TableHead, TableRow, TableBody } from '../ui/table';
import { useConfirm } from '@/providers/confirm-provider';
import { IconButton } from '@/ui/button';
import { MoreVertical_24pxIcon } from '@blocksuite/icons';
import { Menu, MenuItem } from '@/ui/menu';
import { PageMeta, useEditor } from '@/providers/editor-provider';
import { Wrapper } from '@/ui/Layout';
import {
MiddleFavouritesIcon,
MiddleFavouritedStatus2Icon,
} from '@blocksuite/icons';
const StyledTableContainer = styled.div(() => {
return {
@@ -14,19 +21,87 @@ const StyledTableContainer = styled.div(() => {
overflowY: 'auto',
};
});
const StyledTitleWrapper = styled.div(({ theme }) => {
return {
...displayFlex('flex-start', 'center'),
'favorite-heart': {},
};
});
const StyledTitleContent = styled.div(({ theme }) => {
return {
maxWidth: '90%',
marginRight: '18px',
...textEllipsis(1),
};
});
const StyledFavoriteButton = styled.button<{ favorite: boolean }>(
({ theme, favorite }) => {
return {
width: '32px',
height: '32px',
justifyContent: 'center',
alignItems: 'center',
display: 'none',
color: favorite ? theme.colors.primaryColor : theme.colors.iconColor,
'&:hover': {
color: theme.colors.primaryColor,
},
};
}
);
const StyledTableRow = styled(TableRow)(({ theme }) => {
return {
'&:hover': {
'.favorite-button': {
display: 'flex',
},
},
};
});
const OperationMenu = () => {
return (
const OperationArea = ({ pageMeta }: { pageMeta: PageMeta }) => {
const { id, favorite } = pageMeta;
const { openPage, toggleFavoritePage, toggleDeletePage } = useEditor();
const OperationMenu = (
<>
<MenuItem>Add to favourites</MenuItem>
<MenuItem>Open in new tab</MenuItem>
<MenuItem>Delete</MenuItem>
<MenuItem
onClick={() => {
toggleFavoritePage(id);
}}
>
{favorite ? 'Remove' : 'Add'} to favourites
</MenuItem>
<MenuItem
onClick={() => {
openPage(id);
}}
>
Open in new tab
</MenuItem>
<MenuItem
onClick={() => {
toggleDeletePage(id);
}}
>
Delete
</MenuItem>
</>
);
return (
<Wrapper alignItems="center" justifyContent="center">
<Menu content={OperationMenu} placement="bottom-end" disablePortal={true}>
<IconButton hoverBackground="#E0E6FF">
<MoreVertical_24pxIcon />
</IconButton>
</Menu>
</Wrapper>
);
};
export const AllPage = () => {
const { confirm } = useConfirm();
const { pageList, toggleFavoritePage } = useEditor();
return (
<>
<Header />
@@ -53,27 +128,35 @@ export const AllPage = () => {
</TableRow>
</TableHead>
<TableBody>
{new Array(100).fill(0).map((_, index) => {
{pageList.map((pageMeta, index) => {
return (
<TableRow key={index}>
<TableCell ellipsis={true}>
This is a long, very long, extremely long, incredibly long,
exceedingly long, very long document title
</TableCell>
<TableCell ellipsis={true}>2022-11-02 18:30</TableCell>
<TableCell ellipsis={true}>2022-11-02 18:30</TableCell>
<StyledTableRow key={`${pageMeta.id}-${index}`}>
<TableCell>
<Menu
content={<OperationMenu />}
placement="bottom-end"
disablePortal={true}
>
<IconButton hoverBackground="#E0E6FF">
<MoreVertical_24pxIcon />
</IconButton>
</Menu>
<StyledTitleWrapper>
<StyledTitleContent>
{pageMeta.title || pageMeta.id}
</StyledTitleContent>
<StyledFavoriteButton
className="favorite-button"
favorite={pageMeta.favorite}
onClick={() => {
toggleFavoritePage(pageMeta.id);
}}
>
{pageMeta.favorite ? (
<MiddleFavouritedStatus2Icon />
) : (
<MiddleFavouritesIcon />
)}
</StyledFavoriteButton>
</StyledTitleWrapper>
</TableCell>
</TableRow>
<TableCell ellipsis={true}>{pageMeta.createDate}</TableCell>
<TableCell ellipsis={true}>{pageMeta.createDate}</TableCell>
<TableCell>
<OperationArea pageMeta={pageMeta} />
</TableCell>
</StyledTableRow>
);
})}
</TableBody>
@@ -6,7 +6,14 @@ import Loading from './loading';
import { Page, Workspace } from '@blocksuite/store';
import { BlockSchema } from '@blocksuite/editor/dist/block-loader';
import { useRouter } from 'next/router';
export interface PageMeta {
id: string;
title: string;
favorite: boolean;
trash: boolean;
createDate: number;
trashDate: number | null;
}
// Blocksuite has to be imported dynamically since it has a lot of effects
const DynamicEditor = dynamic(() => import('./initial-editor'), {
ssr: false,
@@ -17,23 +24,41 @@ type EditorContextValue = {
setMode: (mode: EditorContainer['mode']) => void;
currentPage: Page | null;
editor: EditorContainer | null;
};
pageList: PageMeta[];
} & EditorHandlers;
// type EditorHandlers = {
// createPage: (props: { pageId?: string; title?: '' }) => void;
// openPage: (props: {
// pageId: string;
// query?: { [key: string]: string };
// }) => Promise<boolean>;
// };
type EditorHandlers = {
createPage: (pageId?: string) => void;
openPage: (
pageId: string,
query?: { [key: string]: string }
) => Promise<boolean>;
deletePage: (pageId: string) => void;
recyclePage: (pageId: string) => void;
toggleDeletePage: (pageId: string) => void;
favoritePage: (pageId: string) => void;
unFavoritePage: (pageId: string) => void;
toggleFavoritePage: (pageId: string) => void;
};
type EditorContextProps = PropsWithChildren<{}>;
export const EditorContext = createContext<EditorContextValue>({
mode: 'page',
setMode: () => {},
pageList: [],
currentPage: null,
editor: null,
createPage: () => {},
openPage: async () => {
return false;
},
deletePage: () => {},
recyclePage: () => {},
toggleDeletePage: () => {},
favoritePage: () => {},
unFavoritePage: () => {},
toggleFavoritePage: () => {},
});
export const useEditor = () => useContext(EditorContext);
@@ -45,6 +70,7 @@ export const EditorProvider = ({
const blockSchemaRef = useRef<typeof BlockSchema | null>(null);
const [workspace, setWorkspace] = useState<Workspace | null>(null);
const [currentPage, setCurrentPage] = useState<Page | null>(null);
const [pageList, setPageList] = useState<PageMeta[]>([]);
const [editor, setEditor] = useState<EditorContainer | null>(null);
const [mode, setMode] = useState<EditorContainer['mode']>('page');
@@ -53,18 +79,26 @@ export const EditorProvider = ({
window.dispatchEvent(event);
}, [mode]);
const editorHandler = {
createPage: ({
pageId = new Date().getTime().toString(),
title,
}: {
pageId?: string;
title?: '';
}) => {
useEffect(() => {
if (!workspace) {
return;
}
setPageList(workspace.meta.pages as PageMeta[]);
workspace.meta.pagesUpdated.on(res => {
setPageList(workspace.meta.pages as PageMeta[]);
});
return () => {
// TODO: Does it need to be removed?
workspace.meta.pagesUpdated.dispose();
};
}, [workspace]);
const editorHandler: EditorHandlers = {
createPage: (pageId = new Date().getTime().toString()) => {
blockSchemaRef.current &&
workspace?.createPage(pageId, title).register(blockSchemaRef.current);
workspace?.createPage(pageId).register(blockSchemaRef.current);
},
openPage: (pageId: string, query: { [key: string]: string } = {}) => {
openPage: (pageId, query = {}) => {
return router.push({
pathname: '/',
query: {
@@ -73,25 +107,36 @@ export const EditorProvider = ({
},
});
},
getPageList: () => {
return workspace?.meta.pages;
},
deletePage: (pageId: string) => {
deletePage: pageId => {
workspace?.setPage(pageId, { trash: true });
},
recyclePage: (pageId: string) => {
recyclePage: pageId => {
workspace?.setPage(pageId, { trash: false });
},
favoritePage: (pageId: string) => {
toggleDeletePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPage(pageId, { trash: !pageMeta.trash });
}
},
favoritePage: pageId => {
workspace?.setPage(pageId, { favorite: true });
},
unFavoritePage: (pageId: string) => {
workspace?.setPage(pageId, { favorite: true });
unFavoritePage: pageId => {
workspace?.setPageMeta(pageId, { favorite: true });
},
toggleFavoritePage: pageId => {
const pageMeta = workspace?.meta.pages.find(p => p.id === pageId);
if (pageMeta) {
workspace?.setPageMeta(pageId, { favorite: !pageMeta.favorite });
}
},
};
return (
<EditorContext.Provider value={{ editor, currentPage, mode, setMode }}>
<EditorContext.Provider
value={{ editor, currentPage, mode, setMode, pageList, ...editorHandler }}
>
<DynamicEditor
workspace={workspace}
currentPage={currentPage}
@@ -73,14 +73,21 @@ const InitialEditor = ({
if (!workspace) {
return;
}
let initialPage =
workspace.pages.get(`space:${router.query.pageId}`) ??
[...workspace.pages.values()][0];
if (!initialPage) {
const pageId = `${router.query.pageId}` ?? 'page0';
initialPage = workspace.createPage(pageId).register(BlockSchema);
}
// const initialPageId =
// workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
// ?.id ??
// workspace.meta.pages[0]?.id ??
// 'page0';
const initialPageId =
workspace.meta.pages.find(p => p.id === (router.query.pageId as string))
?.id ?? 'page0';
console.log('initialPageId', initialPageId);
const initialPage = workspace
.createPage(initialPageId)
.register(BlockSchema);
setCurrentPage(initialPage);
}, [workspace, router.query.pageId, setCurrentPage]);
+15 -15
View File
@@ -22,10 +22,10 @@ importers:
packages/app:
specifiers:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/editor': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/icons': ^1.0.5
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
'@emotion/css': ^11.10.0
'@emotion/react': ^11.10.4
'@emotion/server': ^11.10.0
@@ -53,10 +53,10 @@ importers:
react-dom: 18.2.0
typescript: 4.8.3
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/editor': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/editor': 0.3.0-alpha.6
'@blocksuite/icons': 1.0.5_w5j4k42lgipnm43s3brx6h3c34
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
'@emotion/css': 11.10.0
'@emotion/react': 11.10.4_w5j4k42lgipnm43s3brx6h3c34
'@emotion/server': 11.10.0_@emotion+css@11.10.0
@@ -172,10 +172,10 @@ packages:
to-fast-properties: 2.0.0
dev: false
/@blocksuite/blocks/0.3.0-alpha.5:
resolution: {integrity: sha512-jZy1mXaC2s/b227Yf/wNPRwMAFGa1USH/Q0OJ6KAcmY8YQdeGXKAoNTz4p7K5rMJgtE1t17/Mzwo5+exCRbIkg==}
/@blocksuite/blocks/0.3.0-alpha.6:
resolution: {integrity: sha512-pa8wP0hRIDlufae+ABAQFLW8TNOGsfh8AqyTKF/+LVYFCGr+9tlW55X3OlWtU51vFxawst1Wd3FnjCAW6XiaKQ==}
dependencies:
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.6
hotkeys-js: 3.10.0
lit: 2.4.0
quill: 1.3.7
@@ -186,11 +186,11 @@ packages:
- utf-8-validate
dev: false
/@blocksuite/editor/0.3.0-alpha.5:
resolution: {integrity: sha512-H7RZkG3ptyzLs0+6YgwQnp6H8hByfWRSjDi388ZIz3/exgliyBz2QkQwY4Tj2nlAYSq/U5/8hdDMjw4a092Ivw==}
/@blocksuite/editor/0.3.0-alpha.6:
resolution: {integrity: sha512-2wFkOlCKqC4BrfCIzuxjUyVnE/mmGOyUnqVTQNmHrToDS81RLIq0r+lj1IrzLv+LZQCfTyhoAlJyaxUNrUw3sw==}
dependencies:
'@blocksuite/blocks': 0.3.0-alpha.5
'@blocksuite/store': 0.3.0-alpha.5
'@blocksuite/blocks': 0.3.0-alpha.6
'@blocksuite/store': 0.3.0-alpha.6
lit: 2.4.0
marked: 4.1.1
turndown: 7.1.1
@@ -210,8 +210,8 @@ packages:
react: 18.2.0
dev: false
/@blocksuite/store/0.3.0-alpha.5:
resolution: {integrity: sha512-pkbSrwB7KTfW56iH4ZFPkrS6shIU8QpmJlZmKVY95Gp5QSISW2ffKUsFrrHVHT+GoOV7+RPZQrphUnC57grPNg==}
/@blocksuite/store/0.3.0-alpha.6:
resolution: {integrity: sha512-rI7cUVSqoMh1bsNLwL8MAgyaUq0Ix+SRBqweYwVjeDoqFIbHjnRSwkVw48K/FgxN6ekN96HLSf3Sj/HK1ivPpw==}
dependencies:
buffer: 6.0.3
flexsearch: 0.7.21