milestone: publish alpha version (#637)

- document folder
- full-text search
- blob storage
- basic edgeless support

Co-authored-by: tzhangchi <terry.zhangchi@outlook.com>
Co-authored-by: QiShaoXuan <qishaoxuan777@gmail.com>
Co-authored-by: DiamondThree <diamond.shx@gmail.com>
Co-authored-by: MingLiang Wang <mingliangwang0o0@gmail.com>
Co-authored-by: JimmFly <yangjinfei001@gmail.com>
Co-authored-by: Yifeng Wang <doodlewind@toeverything.info>
Co-authored-by: Himself65 <himself65@outlook.com>
Co-authored-by: lawvs <18554747+lawvs@users.noreply.github.com>
Co-authored-by: Qi <474021214@qq.com>
This commit is contained in:
DarkSky
2022-12-30 21:40:15 +08:00
committed by GitHub
parent cc790dcbc2
commit 6c2c7dcd48
296 changed files with 16139 additions and 2072 deletions
@@ -0,0 +1,116 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import {
useRef,
useEffect,
useState,
ReactElement,
PropsWithChildren,
} from 'react';
import { styled } from '@/styles';
import { EditorHeader } from '@/components/header';
import EdgelessToolbar from '@/components/edgeless-toolbar';
import MobileModal from '@/components/mobile-modal';
import { useAppState } from '@/providers/app-state-provider/context';
import exampleMarkdown from '@/templates/Welcome-to-AFFiNE-Alpha-v2.0.md';
import type { NextPageWithLayout } from '../..//_app';
import WorkspaceLayout from '@/components/workspace-layout';
import { useRouter } from 'next/router';
import { usePageHelper } from '@/hooks/use-page-helper';
const StyledEditorContainer = styled('div')(() => {
return {
height: 'calc(100vh - 60px)',
};
});
const Page: NextPageWithLayout = () => {
const editorContainer = useRef<HTMLDivElement>(null);
const { createEditor, setEditor, currentPage, currentWorkspace } =
useAppState();
useEffect(() => {
const ret = () => {
const node = editorContainer.current;
while (node?.firstChild) {
node.removeChild(node.firstChild);
}
};
const editor = createEditor?.current?.(currentPage!);
if (editor) {
editorContainer.current?.appendChild(editor);
setEditor?.current?.(editor);
if (currentPage!.isEmpty) {
const isFirstPage = currentWorkspace?.meta.pageMetas.length === 1;
// Can not use useCurrentPageMeta to get new title, cause meta title will trigger rerender, but the second time can not remove title
const { title: metaTitle } = currentPage!.meta;
const title = metaTitle
? metaTitle
: isFirstPage
? 'Welcome to AFFiNE Alpha "Abbey Wood"'
: '';
currentWorkspace?.setPageMeta(currentPage!.id, { title });
const pageId = currentPage!.addBlock({
flavour: 'affine:page',
title,
});
const groupId = currentPage!.addBlock(
{ flavour: 'affine:group' },
pageId
);
currentPage!.addBlock({ flavour: 'affine:group' }, pageId);
// If this is a first page in workspace, init an introduction markdown
if (isFirstPage) {
editor.clipboard.importMarkdown(exampleMarkdown, `${groupId}`);
currentWorkspace!.setPageMeta(currentPage!.id, { title });
}
currentPage!.resetHistory();
}
}
return ret;
}, [currentWorkspace, currentPage, createEditor, setEditor]);
return (
<>
<EditorHeader />
<MobileModal />
<StyledEditorContainer ref={editorContainer} />
<EdgelessToolbar />
</>
);
};
const PageDefender = ({ children }: PropsWithChildren) => {
const router = useRouter();
const [pageLoaded, setPageLoaded] = useState(false);
const { currentWorkspace, loadPage } = useAppState();
const { createPage } = usePageHelper();
useEffect(() => {
const initPage = async () => {
const pageId = router.query.pageId as string;
const isPageExist = !!currentWorkspace!.meta.pageMetas.find(
p => p.id === pageId
);
if (!isPageExist) {
await createPage({ pageId });
}
await loadPage(pageId);
setPageLoaded(true);
};
initPage();
}, [createPage, currentWorkspace, loadPage, router.query.pageId]);
return <>{pageLoaded ? children : null}</>;
};
Page.getLayout = function getLayout(page: ReactElement) {
return (
<WorkspaceLayout>
<PageDefender>{page}</PageDefender>
</WorkspaceLayout>
);
};
export default Page;
@@ -0,0 +1,26 @@
import { PageList } from '@/components/page-list';
import { AllPagesIcon } from '@blocksuite/icons';
import usePageMetaList from '@/hooks/use-page-meta-list';
import { PageListHeader } from '@/components/header';
import { ReactElement } from 'react';
import WorkspaceLayout from '@/components/workspace-layout';
const All = () => {
const pageMetaList = usePageMetaList();
return (
<>
<PageListHeader icon={<AllPagesIcon />}>All Page</PageListHeader>
<PageList
pageList={pageMetaList.filter(p => !p.trash)}
showFavoriteTag={true}
/>
</>
);
};
All.getLayout = function getLayout(page: ReactElement) {
return <WorkspaceLayout>{page}</WorkspaceLayout>;
};
export default All;
@@ -0,0 +1,20 @@
import { PageListHeader } from '@/components/header';
import { PageList } from '@/components/page-list';
import { FavouritesIcon } from '@blocksuite/icons';
import usePageMetaList from '@/hooks/use-page-meta-list';
import { ReactElement } from 'react';
import WorkspaceLayout from '@/components/workspace-layout';
export const Favorite = () => {
const pageMetaList = usePageMetaList();
return (
<>
<PageListHeader icon={<FavouritesIcon />}>Favourites</PageListHeader>
<PageList pageList={pageMetaList.filter(p => p.favorite && !p.trash)} />
</>
);
};
Favorite.getLayout = function getLayout(page: ReactElement) {
return <WorkspaceLayout>{page}</WorkspaceLayout>;
};
export default Favorite;
@@ -0,0 +1,40 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useAppState } from '@/providers/app-state-provider/context';
import useEnsureWorkspace from '@/hooks/use-ensure-workspace';
import { PageLoading } from '@/components/loading';
import usePageHelper from '@/hooks/use-page-helper';
const WorkspaceIndex = () => {
const router = useRouter();
const { currentWorkspaceId, currentWorkspace } = useAppState();
const { createPage } = usePageHelper();
const { workspaceLoaded } = useEnsureWorkspace();
useEffect(() => {
const initPage = async () => {
if (!workspaceLoaded) {
return;
}
const savedPageId = currentWorkspace?.meta.pageMetas[0]?.id;
if (savedPageId) {
router.replace(`/workspace/${currentWorkspaceId}/${savedPageId}`);
return;
}
const pageId = await createPage();
router.replace(`/workspace/${currentWorkspaceId}/${pageId}`);
};
initPage();
}, [
currentWorkspace,
currentWorkspaceId,
createPage,
router,
workspaceLoaded,
]);
return <PageLoading />;
};
export default WorkspaceIndex;
@@ -0,0 +1,22 @@
import { PageListHeader } from '@/components/header';
import { PageList } from '@/components/page-list';
import { TrashIcon } from '@blocksuite/icons';
import usePageMetaList from '@/hooks/use-page-meta-list';
import { ReactElement } from 'react';
import WorkspaceLayout from '@/components/workspace-layout';
export const Trash = () => {
const pageMetaList = usePageMetaList();
return (
<>
<PageListHeader icon={<TrashIcon />}>Trash</PageListHeader>
<PageList pageList={pageMetaList.filter(p => p.trash)} isTrash={true} />
</>
);
};
Trash.getLayout = function getLayout(page: ReactElement) {
return <WorkspaceLayout>{page}</WorkspaceLayout>;
};
export default Trash;
@@ -0,0 +1,21 @@
import { useEffect } from 'react';
import { useRouter } from 'next/router';
import { useAppState } from '@/providers/app-state-provider';
import useEnsureWorkspace from '@/hooks/use-ensure-workspace';
import { PageLoading } from '@/components/loading';
export const WorkspaceIndex = () => {
const router = useRouter();
const { currentWorkspaceId } = useAppState();
const { workspaceLoaded } = useEnsureWorkspace();
useEffect(() => {
if (workspaceLoaded) {
router.push(`/workspace/${currentWorkspaceId}`);
}
}, [currentWorkspaceId, router, workspaceLoaded]);
return <PageLoading />;
};
export default WorkspaceIndex;