mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
Merge branch 'feat/poc' of github.com:toeverything/AFFiNE into feat/poc
This commit is contained in:
@@ -4,7 +4,6 @@ import { Button } from '@/ui/button';
|
||||
import { useState } from 'react';
|
||||
import { createWorkspace } from '@/hooks/mock-data/mock';
|
||||
import Input from '@/ui/input';
|
||||
|
||||
interface ModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
|
||||
@@ -12,9 +12,14 @@ import {
|
||||
SignOut,
|
||||
} from '@/hooks/mock-data/mock';
|
||||
import { CreateWorkspaceModal } from '../create-workspace';
|
||||
import {
|
||||
CloudUnsyncedIcon,
|
||||
CloudInsyncIcon,
|
||||
UsersIcon,
|
||||
AddIcon,
|
||||
} from '@blocksuite/icons';
|
||||
import { useConfirm } from '@/providers/confirm-provider';
|
||||
import { toast } from '@/ui/toast';
|
||||
|
||||
interface LoginModalProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
@@ -42,12 +47,11 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
|
||||
<div>
|
||||
<Modal open={open} onClose={onClose}>
|
||||
<ModalWrapper
|
||||
width={620}
|
||||
height={334}
|
||||
width={820}
|
||||
style={{ padding: '10px', display: 'flex', flexDirection: 'column' }}
|
||||
>
|
||||
<Header>
|
||||
<ContentTitle>My Workspace List</ContentTitle>
|
||||
<ContentTitle>My Workspaces</ContentTitle>
|
||||
<ModalCloseButton
|
||||
top={6}
|
||||
right={6}
|
||||
@@ -67,11 +71,48 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
|
||||
}}
|
||||
key={item.id}
|
||||
>
|
||||
<span>{item.name}</span>/
|
||||
{item.type === 'local' && <b>local</b>}
|
||||
{item.type === 'join' && <b>join</b>}/
|
||||
{item.isPublish ? 'isPublish' : 'isPrivate'}/
|
||||
{item.isLocal ? 'isLocal' : ''}/
|
||||
<span style={{ width: '100px', marginRight: '20px' }}>
|
||||
<svg
|
||||
style={{
|
||||
float: 'left',
|
||||
marginTop: '6px',
|
||||
marginLeft: '10px',
|
||||
marginRight: '10px',
|
||||
}}
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 40 40"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
width="39"
|
||||
height="39"
|
||||
rx="19.5"
|
||||
stroke="#6880FF"
|
||||
fill="#FFF"
|
||||
/>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M18.6303 8.79688L11.2559 29.8393H15.5752L20.2661 15.2858L24.959 29.8393H29.2637L21.8881 8.79688H18.6303Z"
|
||||
fill="#6880FF"
|
||||
/>
|
||||
</svg>
|
||||
{item.name}
|
||||
</span>
|
||||
<span style={{ position: 'relative', top: '6px' }}>
|
||||
{item.type === 'local' && (
|
||||
<CloudUnsyncedIcon fontSize={24} />
|
||||
)}
|
||||
{item.type === 'cloud' && (
|
||||
<CloudInsyncIcon fontSize={24} />
|
||||
)}
|
||||
{item.isPublish && <UsersIcon fontSize={24} />}
|
||||
</span>
|
||||
{/* {item.isLocal ? 'isLocal' : ''}/ */}
|
||||
</WorkspaceItem>
|
||||
);
|
||||
})}
|
||||
@@ -82,10 +123,22 @@ export const WorkspaceModal = ({ open, onClose }: LoginModalProps) => {
|
||||
setCreateWorkspaceOpen(true);
|
||||
}}
|
||||
>
|
||||
Create Workspace
|
||||
<AddIcon
|
||||
style={{
|
||||
fontSize: '20px',
|
||||
top: '4px',
|
||||
position: 'relative',
|
||||
marginRight: '10px',
|
||||
}}
|
||||
/>
|
||||
Create Or Import
|
||||
</Button>
|
||||
</li>
|
||||
</WorkspaceList>
|
||||
<p style={{ fontSize: '14px', color: '#ccc', margin: '12px 0' }}>
|
||||
Tips:Workspace is your virtual space to capture, create and plan
|
||||
as just one person or together as a team.
|
||||
</p>
|
||||
</Content>
|
||||
<Footer>
|
||||
{!user ? (
|
||||
@@ -172,9 +225,10 @@ const WorkspaceList = styled('div')({
|
||||
});
|
||||
|
||||
const WorkspaceItem = styled('div')({
|
||||
border: '1px solid #e5e5e5',
|
||||
padding: '10px',
|
||||
cursor: 'pointer',
|
||||
padding: '8px',
|
||||
border: '1px solid #eee',
|
||||
fontWeight: 'bold',
|
||||
':hover': {
|
||||
background: '#eee',
|
||||
},
|
||||
|
||||
@@ -5,6 +5,7 @@ import type {
|
||||
Workspace as StoreWorkspace,
|
||||
} from '@blocksuite/store';
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
|
||||
export type LoadWorkspaceHandler = (
|
||||
workspaceId: string,
|
||||
user?: AccessTokenMessage | null
|
||||
@@ -20,7 +21,7 @@ export interface AppStateValue {
|
||||
|
||||
currentPage: StorePage | null;
|
||||
|
||||
workspaces: Record<string, StoreWorkspace | null>;
|
||||
// workspaces: Record<string, StoreWorkspace | null>;
|
||||
|
||||
editor: EditorContainer | null;
|
||||
synced: boolean;
|
||||
@@ -53,7 +54,6 @@ export const AppState = createContext<AppStateContext>({
|
||||
synced: false,
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
refreshWorkspacesMeta: () => {},
|
||||
workspaces: {},
|
||||
});
|
||||
|
||||
export const useAppState = () => {
|
||||
|
||||
@@ -2,31 +2,13 @@ import { useEffect } from 'react';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import '@blocksuite/blocks';
|
||||
import { EditorContainer } from '@blocksuite/editor';
|
||||
import type { LoadWorkspaceHandler, CreateEditorHandler } from './context';
|
||||
import { getDataCenter } from '@affine/datacenter';
|
||||
import type { CreateEditorHandler } from './context';
|
||||
|
||||
interface Props {
|
||||
setLoadWorkspaceHandler: (handler: LoadWorkspaceHandler) => void;
|
||||
setCreateEditorHandler: (handler: CreateEditorHandler) => void;
|
||||
}
|
||||
|
||||
const DynamicBlocksuite = ({
|
||||
setLoadWorkspaceHandler,
|
||||
setCreateEditorHandler,
|
||||
}: Props) => {
|
||||
useEffect(() => {
|
||||
const openWorkspace: LoadWorkspaceHandler = async (workspaceId: string) => {
|
||||
if (workspaceId) {
|
||||
const dc = await getDataCenter();
|
||||
return dc.load(workspaceId, { providerId: 'affine' });
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
setLoadWorkspaceHandler(openWorkspace);
|
||||
}, [setLoadWorkspaceHandler]);
|
||||
|
||||
const DynamicBlocksuite = ({ setCreateEditorHandler }: Props) => {
|
||||
useEffect(() => {
|
||||
const createEditorHandler: CreateEditorHandler = (page: Page) => {
|
||||
const editor = new EditorContainer();
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useAppState } from './context';
|
||||
import { usePageHelper } from '@/hooks/use-page-helper';
|
||||
export const useLoadWorkspace = () => {
|
||||
const router = useRouter();
|
||||
const { loadWorkspace, currentWorkspace, currentWorkspaceId } = useAppState();
|
||||
|
||||
const workspaceId = router.query.workspaceId as string;
|
||||
|
||||
useEffect(() => {
|
||||
loadWorkspace?.(workspaceId);
|
||||
}, [workspaceId, loadWorkspace]);
|
||||
|
||||
return currentWorkspaceId === workspaceId ? currentWorkspace : null;
|
||||
};
|
||||
|
||||
export const useLoadPage = () => {
|
||||
const router = useRouter();
|
||||
const { loadPage, currentPage, currentWorkspaceId } = useAppState();
|
||||
const { createPage } = usePageHelper();
|
||||
const workspace = useLoadWorkspace();
|
||||
|
||||
const pageId = router.query.pageId as string;
|
||||
|
||||
useEffect(() => {
|
||||
if (!workspace) {
|
||||
return;
|
||||
}
|
||||
const page = pageId ? workspace?.getPage(pageId) : null;
|
||||
if (page) {
|
||||
loadPage?.(pageId);
|
||||
return;
|
||||
}
|
||||
|
||||
const savedPageId = workspace.meta.pageMetas[0]?.id;
|
||||
if (savedPageId) {
|
||||
router.push(`/workspace/${currentWorkspaceId}/${savedPageId}`);
|
||||
return;
|
||||
}
|
||||
|
||||
createPage().then(async pageId => {
|
||||
if (!pageId) {
|
||||
return;
|
||||
}
|
||||
router.push(`/workspace/${currentWorkspaceId}/${pageId}`);
|
||||
});
|
||||
}, [workspace, pageId, loadPage, createPage, router, currentWorkspaceId]);
|
||||
|
||||
return currentPage?.id === pageId ? currentPage : null;
|
||||
};
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useMemo, useState, useEffect, useCallback, useRef } from 'react';
|
||||
import { useMemo, useState, useCallback, useRef } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { getDataCenter } from '@affine/datacenter';
|
||||
@@ -8,12 +8,20 @@ import type {
|
||||
CreateEditorHandler,
|
||||
LoadWorkspaceHandler,
|
||||
} from './context';
|
||||
import { Page, Workspace as StoreWorkspace } from '@blocksuite/store';
|
||||
import { Page } from '@blocksuite/store';
|
||||
import { EditorContainer } from '@blocksuite/editor';
|
||||
const DynamicBlocksuite = dynamic(() => import('./dynamic-blocksuite'), {
|
||||
ssr: false,
|
||||
});
|
||||
|
||||
const loadWorkspaceHandler: LoadWorkspaceHandler = async workspaceId => {
|
||||
if (workspaceId) {
|
||||
const dc = await getDataCenter();
|
||||
return dc.load(workspaceId, { providerId: 'affine' });
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
const refreshWorkspacesMeta = async () => {
|
||||
const dc = await getDataCenter();
|
||||
@@ -30,43 +38,10 @@ export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
currentWorkspace: null,
|
||||
currentPage: null,
|
||||
editor: null,
|
||||
// Synced is used to ensure that the provider has synced with the server,
|
||||
// So after Synced set to true, the other state is sure to be set.
|
||||
synced: false,
|
||||
refreshWorkspacesMeta,
|
||||
workspaces: {},
|
||||
synced: true,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
(async () => {
|
||||
const workspacesList = await Promise.all(
|
||||
state.workspacesMeta.map(async ({ id }) => {
|
||||
const workspace =
|
||||
(await loadWorkspaceHandler?.(id, state.user)) || null;
|
||||
return { id, workspace };
|
||||
})
|
||||
);
|
||||
const workspaces: Record<string, StoreWorkspace | null> = {};
|
||||
workspacesList.forEach(({ id, workspace }) => {
|
||||
workspaces[id] = workspace;
|
||||
});
|
||||
setState(state => ({
|
||||
...state,
|
||||
workspaces,
|
||||
}));
|
||||
})();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [state.workspacesMeta]);
|
||||
|
||||
const [loadWorkspaceHandler, _setLoadWorkspaceHandler] =
|
||||
useState<LoadWorkspaceHandler>();
|
||||
const setLoadWorkspaceHandler = useCallback(
|
||||
(handler: LoadWorkspaceHandler) => {
|
||||
_setLoadWorkspaceHandler(() => handler);
|
||||
},
|
||||
[_setLoadWorkspaceHandler]
|
||||
);
|
||||
|
||||
const [createEditorHandler, _setCreateEditorHandler] =
|
||||
useState<CreateEditorHandler>();
|
||||
|
||||
@@ -85,7 +60,7 @@ export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
return state.currentWorkspace;
|
||||
}
|
||||
const workspace =
|
||||
(await loadWorkspaceHandler?.(workspaceId, state.user)) || null;
|
||||
(await loadWorkspaceHandler(workspaceId, state.user)) || null;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-expect-error
|
||||
@@ -103,6 +78,7 @@ export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
}));
|
||||
return workspace;
|
||||
};
|
||||
|
||||
const loadPage = useRef<AppStateContext['loadPage']>(() =>
|
||||
Promise.resolve(null)
|
||||
);
|
||||
@@ -147,17 +123,6 @@ export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
setState(state => ({ ...state, editor }));
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!loadWorkspaceHandler) {
|
||||
return;
|
||||
}
|
||||
setState(state => ({
|
||||
...state,
|
||||
workspacesMeta: [],
|
||||
synced: true,
|
||||
}));
|
||||
}, [loadWorkspaceHandler]);
|
||||
|
||||
const context = useMemo(
|
||||
() => ({
|
||||
...state,
|
||||
@@ -172,10 +137,7 @@ export const AppStateProvider = ({ children }: { children?: ReactNode }) => {
|
||||
|
||||
return (
|
||||
<AppState.Provider value={context}>
|
||||
<DynamicBlocksuite
|
||||
setLoadWorkspaceHandler={setLoadWorkspaceHandler}
|
||||
setCreateEditorHandler={setCreateEditorHandler}
|
||||
/>
|
||||
<DynamicBlocksuite setCreateEditorHandler={setCreateEditorHandler} />
|
||||
{children}
|
||||
</AppState.Provider>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user