refactor: rename WorkspacePlugin to WorkspaceAdapter (#2330)

This commit is contained in:
Himself65
2023-05-12 01:43:39 +08:00
committed by LongYinan
parent 5516c215cd
commit 5008958e84
28 changed files with 189 additions and 83 deletions

View File

@@ -19,7 +19,7 @@ import type { Page } from '@blocksuite/store';
import { createStore } from 'jotai'; import { createStore } from 'jotai';
import { describe, expect, test } from 'vitest'; import { describe, expect, test } from 'vitest';
import { WorkspacePlugins } from '../../plugins'; import { WorkspaceAdapters } from '../../plugins';
import { rootCurrentWorkspaceAtom } from '../root'; import { rootCurrentWorkspaceAtom } from '../root';
describe('currentWorkspace atom', () => { describe('currentWorkspace atom', () => {
@@ -45,7 +45,7 @@ describe('currentWorkspace atom', () => {
const provider = createIndexedDBDownloadProvider(workspace); const provider = createIndexedDBDownloadProvider(workspace);
provider.sync(); provider.sync();
await provider.whenReady; await provider.whenReady;
const workspaceId = await WorkspacePlugins[ const workspaceId = await WorkspaceAdapters[
WorkspaceFlavour.LOCAL WorkspaceFlavour.LOCAL
].CRUD.create(workspace); ].CRUD.create(workspace);
store.set(rootWorkspacesMetadataAtom, [ store.set(rootWorkspacesMetadataAtom, [

View File

@@ -12,7 +12,7 @@ import { atom } from 'jotai';
import { atomWithStorage } from 'jotai/utils'; import { atomWithStorage } from 'jotai/utils';
import type { CreateWorkspaceMode } from '../components/affine/create-workspace-modal'; import type { CreateWorkspaceMode } from '../components/affine/create-workspace-modal';
import { WorkspacePlugins } from '../plugins'; import { WorkspaceAdapters } from '../plugins';
const logger = new DebugLogger('web:atoms'); const logger = new DebugLogger('web:atoms');
@@ -25,7 +25,7 @@ export const currentWorkspaceIdAtom = rootCurrentWorkspaceIdAtom;
// todo(himself65): move this to the workspace package // todo(himself65): move this to the workspace package
rootWorkspacesMetadataAtom.onMount = setAtom => { rootWorkspacesMetadataAtom.onMount = setAtom => {
function createFirst(): RootWorkspaceMetadata[] { function createFirst(): RootWorkspaceMetadata[] {
const Plugins = Object.values(WorkspacePlugins).sort( const Plugins = Object.values(WorkspaceAdapters).sort(
(a, b) => a.loadPriority - b.loadPriority (a, b) => a.loadPriority - b.loadPriority
); );

View File

@@ -13,7 +13,7 @@ import { WorkspaceFlavour } from '@affine/workspace/type';
import { assertExists } from '@blocksuite/store'; import { assertExists } from '@blocksuite/store';
import { atom } from 'jotai'; import { atom } from 'jotai';
import { WorkspacePlugins } from '../plugins'; import { WorkspaceAdapters } from '../plugins';
import type { AllWorkspace } from '../shared'; import type { AllWorkspace } from '../shared';
const logger = new DebugLogger('web:atoms:root'); const logger = new DebugLogger('web:atoms:root');
@@ -22,7 +22,7 @@ const logger = new DebugLogger('web:atoms:root');
* Fetch all workspaces from the Plugin CRUD * Fetch all workspaces from the Plugin CRUD
*/ */
export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => { export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => {
const flavours: string[] = Object.values(WorkspacePlugins).map( const flavours: string[] = Object.values(WorkspaceAdapters).map(
plugin => plugin.flavour plugin => plugin.flavour
); );
const jotaiWorkspaces = get(rootWorkspacesMetadataAtom) const jotaiWorkspaces = get(rootWorkspacesMetadataAtom)
@@ -38,7 +38,7 @@ export const workspacesAtom = atom<Promise<AllWorkspace[]>>(async get => {
const workspaces = await Promise.all( const workspaces = await Promise.all(
jotaiWorkspaces.map(workspace => { jotaiWorkspaces.map(workspace => {
const plugin = const plugin =
WorkspacePlugins[workspace.flavour as keyof typeof WorkspacePlugins]; WorkspaceAdapters[workspace.flavour as keyof typeof WorkspaceAdapters];
assertExists(plugin); assertExists(plugin);
const { CRUD } = plugin; const { CRUD } = plugin;
return CRUD.get(workspace.id).then(workspace => { return CRUD.get(workspace.id).then(workspace => {
@@ -93,7 +93,7 @@ export const rootCurrentWorkspaceAtom = atom<Promise<AllWorkspace>>(
if (!targetWorkspace) { if (!targetWorkspace) {
throw new Error(`cannot find the workspace with id ${targetId}.`); throw new Error(`cannot find the workspace with id ${targetId}.`);
} }
const workspace = await WorkspacePlugins[targetWorkspace.flavour].CRUD.get( const workspace = await WorkspaceAdapters[targetWorkspace.flavour].CRUD.get(
targetWorkspace.id targetWorkspace.id
); );
if (!workspace) { if (!workspace) {

View File

@@ -2,7 +2,10 @@ import { Button, IconButton, Menu, MenuItem, Wrapper } from '@affine/component';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { PermissionType } from '@affine/workspace/affine/api'; import { PermissionType } from '@affine/workspace/affine/api';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { import {
DeleteTemporarilyIcon, DeleteTemporarilyIcon,
@@ -37,7 +40,7 @@ import {
const AffineRemoteCollaborationPanel: React.FC< const AffineRemoteCollaborationPanel: React.FC<
Omit<PanelProps, 'workspace'> & { Omit<PanelProps, 'workspace'> & {
workspace: AffineWorkspace; workspace: AffineLegacyCloudWorkspace;
} }
> = ({ workspace }) => { > = ({ workspace }) => {
const [isInviteModalShow, setIsInviteModalShow] = useState(false); const [isInviteModalShow, setIsInviteModalShow] = useState(false);
@@ -214,7 +217,7 @@ const LocalCollaborationPanel: React.FC<
export const CollaborationPanel: React.FC<PanelProps> = props => { export const CollaborationPanel: React.FC<PanelProps> = props => {
switch (props.workspace.flavour) { switch (props.workspace.flavour) {
case WorkspaceFlavour.AFFINE: { case WorkspaceFlavour.AFFINE: {
const workspace = props.workspace as AffineWorkspace; const workspace = props.workspace as AffineLegacyCloudWorkspace;
return ( return (
<AffineRemoteCollaborationPanel {...props} workspace={workspace} /> <AffineRemoteCollaborationPanel {...props} workspace={workspace} />
); );

View File

@@ -7,7 +7,10 @@ import {
} from '@affine/component'; } from '@affine/component';
import { config } from '@affine/env'; import { config } from '@affine/env';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { Box } from '@mui/material'; import { Box } from '@mui/material';
import type React from 'react'; import type React from 'react';
@@ -26,7 +29,7 @@ export type PublishPanelProps = WorkspaceSettingDetailProps & {
}; };
export type PublishPanelAffineProps = WorkspaceSettingDetailProps & { export type PublishPanelAffineProps = WorkspaceSettingDetailProps & {
workspace: AffineWorkspace; workspace: AffineLegacyCloudWorkspace;
}; };
const PublishPanelAffine: React.FC<PublishPanelAffineProps> = ({ const PublishPanelAffine: React.FC<PublishPanelAffineProps> = ({

View File

@@ -1,6 +1,9 @@
import { ShareMenu } from '@affine/component/share-menu'; import { ShareMenu } from '@affine/component/share-menu';
import { config } from '@affine/env'; import { config } from '@affine/env';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import type { Page } from '@blocksuite/store'; import type { Page } from '@blocksuite/store';
import { assertEquals } from '@blocksuite/store'; import { assertEquals } from '@blocksuite/store';
@@ -19,12 +22,12 @@ import type { BaseHeaderProps } from '../header';
const AffineHeaderShareMenu: React.FC<BaseHeaderProps> = props => { const AffineHeaderShareMenu: React.FC<BaseHeaderProps> = props => {
// todo: these hooks should be moved to the top level // todo: these hooks should be moved to the top level
const togglePublish = useToggleWorkspacePublish( const togglePublish = useToggleWorkspacePublish(
props.workspace as AffineWorkspace props.workspace as AffineLegacyCloudWorkspace
); );
const helper = useRouterHelper(useRouter()); const helper = useRouterHelper(useRouter());
return ( return (
<ShareMenu <ShareMenu
workspace={props.workspace as AffineWorkspace} workspace={props.workspace as AffineLegacyCloudWorkspace}
currentPage={props.currentPage as Page} currentPage={props.currentPage as Page}
onEnableAffineCloud={useCallback(async () => { onEnableAffineCloud={useCallback(async () => {
throw new Unreachable( throw new Unreachable(

View File

@@ -9,7 +9,10 @@ import {
import { WorkspaceList } from '@affine/component/workspace-list'; import { WorkspaceList } from '@affine/component/workspace-list';
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { AccessTokenMessage } from '@affine/workspace/affine/login'; import type { AccessTokenMessage } from '@affine/workspace/affine/login';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { HelpIcon, ImportIcon, PlusIcon } from '@blocksuite/icons'; import { HelpIcon, ImportIcon, PlusIcon } from '@blocksuite/icons';
import type { DragEndEvent } from '@dnd-kit/core'; import type { DragEndEvent } from '@dnd-kit/core';
@@ -109,7 +112,7 @@ export const WorkspaceListModal = ({
items={ items={
workspaces.filter( workspaces.filter(
({ flavour }) => flavour !== WorkspaceFlavour.PUBLIC ({ flavour }) => flavour !== WorkspaceFlavour.PUBLIC
) as (AffineWorkspace | LocalWorkspace)[] ) as (AffineLegacyCloudWorkspace | LocalWorkspace)[]
} }
currentWorkspaceId={currentWorkspaceId} currentWorkspaceId={currentWorkspaceId}
onClick={onClickWorkspace} onClick={onClickWorkspace}

View File

@@ -2,12 +2,12 @@ import { WorkspaceFlavour } from '@affine/workspace/type';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { WorkspacePlugins } from '../../plugins'; import { WorkspaceAdapters } from '../../plugins';
export function useAffineLogIn() { export function useAffineLogIn() {
const router = useRouter(); const router = useRouter();
return useCallback(async () => { return useCallback(async () => {
await WorkspacePlugins[WorkspaceFlavour.AFFINE].Events[ await WorkspaceAdapters[WorkspaceFlavour.AFFINE].Events[
'workspace:access' 'workspace:access'
]?.(); ]?.();
// todo: remove reload page requirement // todo: remove reload page requirement

View File

@@ -2,12 +2,12 @@ import { WorkspaceFlavour } from '@affine/workspace/type';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { WorkspacePlugins } from '../../plugins'; import { WorkspaceAdapters } from '../../plugins';
export function useAffineLogOut() { export function useAffineLogOut() {
const router = useRouter(); const router = useRouter();
return useCallback(async () => { return useCallback(async () => {
await WorkspacePlugins[WorkspaceFlavour.AFFINE].Events[ await WorkspaceAdapters[WorkspaceFlavour.AFFINE].Events[
'workspace:revoke' 'workspace:revoke'
]?.(); ]?.();
router.reload(); router.reload();

View File

@@ -1,12 +1,14 @@
import { rootStore, rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootStore, rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import type { AffineWorkspace } from '@affine/workspace/type'; import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type';
import { useCallback } from 'react'; import { useCallback } from 'react';
import useSWR from 'swr'; import useSWR from 'swr';
import { QueryKey } from '../../plugins/affine/fetcher'; import { QueryKey } from '../../plugins/affine/fetcher';
import { affineApis } from '../../shared/apis'; import { affineApis } from '../../shared/apis';
export function useToggleWorkspacePublish(workspace: AffineWorkspace) { export function useToggleWorkspacePublish(
workspace: AffineLegacyCloudWorkspace
) {
const { mutate } = useSWR(QueryKey.getWorkspaces); const { mutate } = useSWR(QueryKey.getWorkspaces);
return useCallback( return useCallback(
async (isPublish: boolean) => { async (isPublish: boolean) => {

View File

@@ -7,7 +7,7 @@ import type { WorkspaceRegistry } from '@affine/workspace/type';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { WorkspacePlugins } from '../plugins'; import { WorkspaceAdapters } from '../plugins';
/** /**
* Transform workspace from one flavour to another * Transform workspace from one flavour to another
@@ -23,8 +23,8 @@ export function useTransformWorkspace() {
to: To, to: To,
workspace: WorkspaceRegistry[From] workspace: WorkspaceRegistry[From]
): Promise<string> => { ): Promise<string> => {
await WorkspacePlugins[from].CRUD.delete(workspace as any); await WorkspaceAdapters[from].CRUD.delete(workspace as any);
const newId = await WorkspacePlugins[to].CRUD.create( const newId = await WorkspaceAdapters[to].CRUD.create(
workspace.blockSuiteWorkspace workspace.blockSuiteWorkspace
); );
set(workspaces => { set(workspaces => {

View File

@@ -9,7 +9,7 @@ import { useAtomValue, useSetAtom } from 'jotai';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
import { workspacesAtom } from '../atoms'; import { workspacesAtom } from '../atoms';
import { WorkspacePlugins } from '../plugins'; import { WorkspaceAdapters } from '../plugins';
import { LocalPlugin } from '../plugins/local'; import { LocalPlugin } from '../plugins/local';
import type { AllWorkspace } from '../shared'; import type { AllWorkspace } from '../shared';
@@ -86,7 +86,7 @@ export function useAppHelper() {
} }
// delete workspace from plugin // delete workspace from plugin
await WorkspacePlugins[targetWorkspace.flavour].CRUD.delete( await WorkspaceAdapters[targetWorkspace.flavour].CRUD.delete(
// fixme: type casting // fixme: type casting
targetWorkspace as any targetWorkspace as any
); );

View File

@@ -39,7 +39,7 @@ import { useRouterWithWorkspaceIdDefense } from '../hooks/use-router-with-worksp
import { useSyncRouterWithCurrentPageId } from '../hooks/use-sync-router-with-current-page-id'; import { useSyncRouterWithCurrentPageId } from '../hooks/use-sync-router-with-current-page-id';
import { useSyncRouterWithCurrentWorkspaceId } from '../hooks/use-sync-router-with-current-workspace-id'; import { useSyncRouterWithCurrentWorkspaceId } from '../hooks/use-sync-router-with-current-workspace-id';
import { useWorkspaces } from '../hooks/use-workspaces'; import { useWorkspaces } from '../hooks/use-workspaces';
import { WorkspacePlugins } from '../plugins'; import { WorkspaceAdapters } from '../plugins';
import { ModalProvider } from '../providers/modal-provider'; import { ModalProvider } from '../providers/modal-provider';
import { pathGenerator, publicPathGenerator } from '../shared'; import { pathGenerator, publicPathGenerator } from '../shared';
@@ -100,7 +100,7 @@ export const QuickSearch: FC = () => {
const logger = new DebugLogger('workspace-layout'); const logger = new DebugLogger('workspace-layout');
const affineGlobalChannel = createAffineGlobalChannel( const affineGlobalChannel = createAffineGlobalChannel(
WorkspacePlugins[WorkspaceFlavour.AFFINE].CRUD WorkspaceAdapters[WorkspaceFlavour.AFFINE].CRUD
); );
export const AllWorkspaceContext = ({ export const AllWorkspaceContext = ({
@@ -170,7 +170,7 @@ export const WorkspaceLayout: FC<PropsWithChildren> =
useEffect(() => { useEffect(() => {
logger.info('mount'); logger.info('mount');
const controller = new AbortController(); const controller = new AbortController();
const lists = Object.values(WorkspacePlugins) const lists = Object.values(WorkspaceAdapters)
.sort((a, b) => a.loadPriority - b.loadPriority) .sort((a, b) => a.loadPriority - b.loadPriority)
.map(({ CRUD }) => CRUD.list); .map(({ CRUD }) => CRUD.list);
@@ -220,7 +220,7 @@ export const WorkspaceLayout: FC<PropsWithChildren> =
}, [currentWorkspaceId, jotaiWorkspaces]); }, [currentWorkspaceId, jotaiWorkspaces]);
const Provider = const Provider =
(meta && WorkspacePlugins[meta.flavour].UI.Provider) ?? DefaultProvider; (meta && WorkspaceAdapters[meta.flavour].UI.Provider) ?? DefaultProvider;
return ( return (
<> <>
{/* fixme(himself65): don't re-render whole modals */} {/* fixme(himself65): don't re-render whole modals */}

View File

@@ -23,7 +23,7 @@ import { useSyncRecentViewsWithRouter } from '../../../hooks/use-recent-views';
import { useRouterAndWorkspaceWithPageIdDefense } from '../../../hooks/use-router-and-workspace-with-page-id-defense'; import { useRouterAndWorkspaceWithPageIdDefense } from '../../../hooks/use-router-and-workspace-with-page-id-defense';
import { useRouterHelper } from '../../../hooks/use-router-helper'; import { useRouterHelper } from '../../../hooks/use-router-helper';
import { WorkspaceLayout } from '../../../layouts/workspace-layout'; import { WorkspaceLayout } from '../../../layouts/workspace-layout';
import { WorkspacePlugins } from '../../../plugins'; import { WorkspaceAdapters } from '../../../plugins';
import type { BlockSuiteWorkspace, NextPageWithLayout } from '../../../shared'; import type { BlockSuiteWorkspace, NextPageWithLayout } from '../../../shared';
function setEditorFlags(blockSuiteWorkspace: BlockSuiteWorkspace) { function setEditorFlags(blockSuiteWorkspace: BlockSuiteWorkspace) {
@@ -85,7 +85,8 @@ const WorkspaceDetail: React.FC = () => {
} }
}, [currentWorkspace]); }, [currentWorkspace]);
if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) { if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) {
const PageDetail = WorkspacePlugins[currentWorkspace.flavour].UI.PageDetail; const PageDetail =
WorkspaceAdapters[currentWorkspace.flavour].UI.PageDetail;
return ( return (
<PageDetail <PageDetail
currentWorkspace={currentWorkspace} currentWorkspace={currentWorkspace}
@@ -93,7 +94,8 @@ const WorkspaceDetail: React.FC = () => {
/> />
); );
} else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) { } else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) {
const PageDetail = WorkspacePlugins[currentWorkspace.flavour].UI.PageDetail; const PageDetail =
WorkspaceAdapters[currentWorkspace.flavour].UI.PageDetail;
return ( return (
<PageDetail <PageDetail
currentWorkspace={currentWorkspace} currentWorkspace={currentWorkspace}

View File

@@ -16,7 +16,7 @@ import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspac
import { useRouterHelper } from '../../../hooks/use-router-helper'; import { useRouterHelper } from '../../../hooks/use-router-helper';
import { useSyncRouterWithCurrentWorkspaceId } from '../../../hooks/use-sync-router-with-current-workspace-id'; import { useSyncRouterWithCurrentWorkspaceId } from '../../../hooks/use-sync-router-with-current-workspace-id';
import { WorkspaceLayout } from '../../../layouts/workspace-layout'; import { WorkspaceLayout } from '../../../layouts/workspace-layout';
import { WorkspacePlugins } from '../../../plugins'; import { WorkspaceAdapters } from '../../../plugins';
import type { NextPageWithLayout } from '../../../shared'; import type { NextPageWithLayout } from '../../../shared';
const AllPage: NextPageWithLayout = () => { const AllPage: NextPageWithLayout = () => {
@@ -43,7 +43,7 @@ const AllPage: NextPageWithLayout = () => {
throw new QueryParamError('workspaceId', router.query.workspaceId); throw new QueryParamError('workspaceId', router.query.workspaceId);
} }
if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) { if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) {
const PageList = WorkspacePlugins[currentWorkspace.flavour].UI.PageList; const PageList = WorkspaceAdapters[currentWorkspace.flavour].UI.PageList;
return ( return (
<> <>
<Head> <Head>
@@ -65,7 +65,7 @@ const AllPage: NextPageWithLayout = () => {
</> </>
); );
} else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) { } else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) {
const PageList = WorkspacePlugins[currentWorkspace.flavour].UI.PageList; const PageList = WorkspaceAdapters[currentWorkspace.flavour].UI.PageList;
return ( return (
<> <>
<Head> <Head>

View File

@@ -22,7 +22,7 @@ import { useOnTransformWorkspace } from '../../../hooks/root/use-on-transform-wo
import { useSyncRouterWithCurrentWorkspaceId } from '../../../hooks/use-sync-router-with-current-workspace-id'; import { useSyncRouterWithCurrentWorkspaceId } from '../../../hooks/use-sync-router-with-current-workspace-id';
import { useAppHelper } from '../../../hooks/use-workspaces'; import { useAppHelper } from '../../../hooks/use-workspaces';
import { WorkspaceLayout } from '../../../layouts/workspace-layout'; import { WorkspaceLayout } from '../../../layouts/workspace-layout';
import { WorkspacePlugins } from '../../../plugins'; import { WorkspaceAdapters } from '../../../plugins';
import type { NextPageWithLayout } from '../../../shared'; import type { NextPageWithLayout } from '../../../shared';
import { toast } from '../../../utils'; import { toast } from '../../../utils';
@@ -116,7 +116,7 @@ const SettingPage: NextPageWithLayout = () => {
return <PageLoading />; return <PageLoading />;
} else if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) { } else if (currentWorkspace.flavour === WorkspaceFlavour.AFFINE) {
const Setting = const Setting =
WorkspacePlugins[currentWorkspace.flavour].UI.SettingsDetail; WorkspaceAdapters[currentWorkspace.flavour].UI.SettingsDetail;
return ( return (
<> <>
<Head> <Head>
@@ -142,7 +142,7 @@ const SettingPage: NextPageWithLayout = () => {
); );
} else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) { } else if (currentWorkspace.flavour === WorkspaceFlavour.LOCAL) {
const Setting = const Setting =
WorkspacePlugins[currentWorkspace.flavour].UI.SettingsDetail; WorkspaceAdapters[currentWorkspace.flavour].UI.SettingsDetail;
return ( return (
<> <>
<Head> <Head>

View File

@@ -1,5 +1,5 @@
import { rootStore } from '@affine/workspace/atom'; import { rootStore } from '@affine/workspace/atom';
import type { AffineWorkspace } from '@affine/workspace/type'; import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import { assertExists } from '@blocksuite/store'; import { assertExists } from '@blocksuite/store';
@@ -70,7 +70,7 @@ export const fetcher = async (
workspaceApis: affineApis, workspaceApis: affineApis,
} }
); );
const remWorkspace: AffineWorkspace = { const remWorkspace: AffineLegacyCloudWorkspace = {
...workspace, ...workspace,
flavour: WorkspaceFlavour.AFFINE, flavour: WorkspaceFlavour.AFFINE,
blockSuiteWorkspace, blockSuiteWorkspace,

View File

@@ -11,8 +11,12 @@ import {
SignMethod, SignMethod,
} from '@affine/workspace/affine/login'; } from '@affine/workspace/affine/login';
import { rootStore, rootWorkspacesMetadataAtom } from '@affine/workspace/atom'; import { rootStore, rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import type { AffineWorkspace } from '@affine/workspace/type'; import type { AffineLegacyCloudWorkspace } from '@affine/workspace/type';
import { LoadPriority, WorkspaceFlavour } from '@affine/workspace/type'; import {
LoadPriority,
ReleaseType,
WorkspaceFlavour,
} from '@affine/workspace/type';
import { import {
cleanupWorkspace, cleanupWorkspace,
createEmptyBlockSuiteWorkspace, createEmptyBlockSuiteWorkspace,
@@ -33,7 +37,7 @@ import { useAffineRefreshAuthToken } from '../../hooks/affine/use-affine-refresh
import { BlockSuiteWorkspace } from '../../shared'; import { BlockSuiteWorkspace } from '../../shared';
import { affineApis } from '../../shared/apis'; import { affineApis } from '../../shared/apis';
import { toast } from '../../utils'; import { toast } from '../../utils';
import type { WorkspacePlugin } from '..'; import type { WorkspaceAdapter } from '..';
import { QueryKey } from './fetcher'; import { QueryKey } from './fetcher';
const storage = createJSONStorage(() => localStorage); const storage = createJSONStorage(() => localStorage);
@@ -46,7 +50,7 @@ const schema = z.object({
const getPersistenceAllWorkspace = () => { const getPersistenceAllWorkspace = () => {
const items = storage.getItem(AFFINE_STORAGE_KEY, []); const items = storage.getItem(AFFINE_STORAGE_KEY, []);
const allWorkspaces: AffineWorkspace[] = []; const allWorkspaces: AffineLegacyCloudWorkspace[] = [];
if ( if (
Array.isArray(items) && Array.isArray(items) &&
items.every(item => schema.safeParse(item).success) items.every(item => schema.safeParse(item).success)
@@ -60,7 +64,7 @@ const getPersistenceAllWorkspace = () => {
workspaceApis: affineApis, workspaceApis: affineApis,
} }
); );
const affineWorkspace: AffineWorkspace = { const affineWorkspace: AffineLegacyCloudWorkspace = {
...item, ...item,
flavour: WorkspaceFlavour.AFFINE, flavour: WorkspaceFlavour.AFFINE,
blockSuiteWorkspace, blockSuiteWorkspace,
@@ -89,7 +93,8 @@ function AuthContext({ children }: PropsWithChildren): ReactElement {
return <>{children}</>; return <>{children}</>;
} }
export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = { export const AffinePlugin: WorkspaceAdapter<WorkspaceFlavour.AFFINE> = {
releaseType: ReleaseType.STABLE,
flavour: WorkspaceFlavour.AFFINE, flavour: WorkspaceFlavour.AFFINE,
loadPriority: LoadPriority.HIGH, loadPriority: LoadPriority.HIGH,
Events: { Events: {
@@ -178,7 +183,8 @@ export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = {
cleanupWorkspace(WorkspaceFlavour.AFFINE); cleanupWorkspace(WorkspaceFlavour.AFFINE);
return null; return null;
} }
const workspaces: AffineWorkspace[] = await AffinePlugin.CRUD.list(); const workspaces: AffineLegacyCloudWorkspace[] =
await AffinePlugin.CRUD.list();
return ( return (
workspaces.find(workspace => workspace.id === workspaceId) ?? null workspaces.find(workspace => workspace.id === workspaceId) ?? null
); );
@@ -239,7 +245,7 @@ export const AffinePlugin: WorkspacePlugin<WorkspaceFlavour.AFFINE> = {
storage.setItem(AFFINE_STORAGE_KEY, [...data]); storage.setItem(AFFINE_STORAGE_KEY, [...data]);
} }
const affineWorkspace: AffineWorkspace = { const affineWorkspace: AffineLegacyCloudWorkspace = {
...workspace, ...workspace,
flavour: WorkspaceFlavour.AFFINE, flavour: WorkspaceFlavour.AFFINE,
blockSuiteWorkspace, blockSuiteWorkspace,

View File

@@ -3,12 +3,17 @@ import type {
WorkspaceCRUD, WorkspaceCRUD,
WorkspaceUISchema, WorkspaceUISchema,
} from '@affine/workspace/type'; } from '@affine/workspace/type';
import { LoadPriority, WorkspaceFlavour } from '@affine/workspace/type'; import {
LoadPriority,
ReleaseType,
WorkspaceFlavour,
} from '@affine/workspace/type';
import { AffinePlugin } from './affine'; import { AffinePlugin } from './affine';
import { LocalPlugin } from './local'; import { LocalPlugin } from './local';
export interface WorkspacePlugin<Flavour extends WorkspaceFlavour> { export interface WorkspaceAdapter<Flavour extends WorkspaceFlavour> {
releaseType: ReleaseType;
flavour: Flavour; flavour: Flavour;
// Plugin will be loaded according to the priority // Plugin will be loaded according to the priority
loadPriority: LoadPriority; loadPriority: LoadPriority;
@@ -21,10 +26,32 @@ export interface WorkspacePlugin<Flavour extends WorkspaceFlavour> {
const unimplemented = () => { const unimplemented = () => {
throw new Error('Not implemented'); throw new Error('Not implemented');
}; };
export const WorkspacePlugins = {
export const WorkspaceAdapters = {
[WorkspaceFlavour.AFFINE]: AffinePlugin, [WorkspaceFlavour.AFFINE]: AffinePlugin,
[WorkspaceFlavour.LOCAL]: LocalPlugin, [WorkspaceFlavour.LOCAL]: LocalPlugin,
[WorkspaceFlavour.AFFINE_CLOUD]: {
releaseType: ReleaseType.UNRELEASED,
flavour: WorkspaceFlavour.AFFINE_CLOUD,
loadPriority: LoadPriority.HIGH,
Events: {} as Partial<AppEvents>,
// todo: implement this
CRUD: {
get: unimplemented,
list: unimplemented,
delete: unimplemented,
create: unimplemented,
},
// todo: implement this
UI: {
Provider: unimplemented,
PageDetail: unimplemented,
PageList: unimplemented,
SettingsDetail: unimplemented,
},
},
[WorkspaceFlavour.PUBLIC]: { [WorkspaceFlavour.PUBLIC]: {
releaseType: ReleaseType.UNRELEASED,
flavour: WorkspaceFlavour.PUBLIC, flavour: WorkspaceFlavour.PUBLIC,
loadPriority: LoadPriority.LOW, loadPriority: LoadPriority.LOW,
Events: {} as Partial<AppEvents>, Events: {} as Partial<AppEvents>,
@@ -44,5 +71,5 @@ export const WorkspacePlugins = {
}, },
}, },
} satisfies { } satisfies {
[Key in WorkspaceFlavour]: WorkspacePlugin<Key>; [Key in WorkspaceFlavour]: WorkspaceAdapter<Key>;
}; };

View File

@@ -9,7 +9,11 @@ import {
saveWorkspaceToLocalStorage, saveWorkspaceToLocalStorage,
} from '@affine/workspace/local/crud'; } from '@affine/workspace/local/crud';
import { createIndexedDBBackgroundProvider } from '@affine/workspace/providers'; import { createIndexedDBBackgroundProvider } from '@affine/workspace/providers';
import { LoadPriority, WorkspaceFlavour } from '@affine/workspace/type'; import {
LoadPriority,
ReleaseType,
WorkspaceFlavour,
} from '@affine/workspace/type';
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import { nanoid } from '@blocksuite/store'; import { nanoid } from '@blocksuite/store';
import React from 'react'; import React from 'react';
@@ -18,11 +22,12 @@ import { PageNotFoundError } from '../../components/affine/affine-error-eoundary
import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail'; import { WorkspaceSettingDetail } from '../../components/affine/workspace-setting-detail';
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list'; import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { PageDetailEditor } from '../../components/page-detail-editor'; import { PageDetailEditor } from '../../components/page-detail-editor';
import type { WorkspacePlugin } from '..'; import type { WorkspaceAdapter } from '..';
const logger = new DebugLogger('use-create-first-workspace'); const logger = new DebugLogger('use-create-first-workspace');
export const LocalPlugin: WorkspacePlugin<WorkspaceFlavour.LOCAL> = { export const LocalPlugin: WorkspaceAdapter<WorkspaceFlavour.LOCAL> = {
releaseType: ReleaseType.STABLE,
flavour: WorkspaceFlavour.LOCAL, flavour: WorkspaceFlavour.LOCAL,
loadPriority: LoadPriority.LOW, loadPriority: LoadPriority.LOW,
Events: { Events: {

View File

@@ -1,4 +1,7 @@
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import type { AffinePublicWorkspace } from '@affine/workspace/type'; import type { AffinePublicWorkspace } from '@affine/workspace/type';
import type { WorkspaceRegistry } from '@affine/workspace/type'; import type { WorkspaceRegistry } from '@affine/workspace/type';
import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store'; import { Workspace as BlockSuiteWorkspace } from '@blocksuite/store';
@@ -8,7 +11,7 @@ import type { ReactElement, ReactNode } from 'react';
export { BlockSuiteWorkspace }; export { BlockSuiteWorkspace };
export type AffineOfficialWorkspace = export type AffineOfficialWorkspace =
| AffineWorkspace | AffineLegacyCloudWorkspace
| LocalWorkspace | LocalWorkspace
| AffinePublicWorkspace; | AffinePublicWorkspace;

View File

@@ -1,4 +1,7 @@
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { ExportIcon, PublishIcon, ShareIcon } from '@blocksuite/icons'; import { ExportIcon, PublishIcon, ShareIcon } from '@blocksuite/icons';
import type { Page } from '@blocksuite/store'; import type { Page } from '@blocksuite/store';
import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public'; import { useBlockSuiteWorkspacePageIsPublic } from '@toeverything/hooks/use-block-suite-workspace-page-is-public';
@@ -24,8 +27,8 @@ const tabIcons = {
ShareWorkspace: <PublishIcon />, ShareWorkspace: <PublishIcon />,
}; };
export type ShareMenuProps< export type ShareMenuProps<
Workspace extends AffineWorkspace | LocalWorkspace = Workspace extends AffineLegacyCloudWorkspace | LocalWorkspace =
| AffineWorkspace | AffineLegacyCloudWorkspace
| LocalWorkspace | LocalWorkspace
> = { > = {
workspace: Workspace; workspace: Workspace;

View File

@@ -1,5 +1,8 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import type { FC } from 'react'; import type { FC } from 'react';
@@ -26,7 +29,9 @@ const ShareLocalWorkspace: FC<ShareMenuProps<LocalWorkspace>> = props => {
); );
}; };
const ShareAffineWorkspace: FC<ShareMenuProps<AffineWorkspace>> = props => { const ShareAffineWorkspace: FC<
ShareMenuProps<AffineLegacyCloudWorkspace>
> = props => {
const isPublicWorkspace = props.workspace.public; const isPublicWorkspace = props.workspace.public;
const t = useAFFiNEI18N(); const t = useAFFiNEI18N();
return ( return (
@@ -55,7 +60,9 @@ export const ShareWorkspace: FC<ShareMenuProps> = props => {
); );
} else if (props.workspace.flavour === WorkspaceFlavour.AFFINE) { } else if (props.workspace.flavour === WorkspaceFlavour.AFFINE) {
return ( return (
<ShareAffineWorkspace {...(props as ShareMenuProps<AffineWorkspace>)} /> <ShareAffineWorkspace
{...(props as ShareMenuProps<AffineLegacyCloudWorkspace>)}
/>
); );
} }
throw new Error('Unreachable'); throw new Error('Unreachable');

View File

@@ -1,6 +1,6 @@
import type { import type {
AffineLegacyCloudWorkspace,
AffinePublicWorkspace, AffinePublicWorkspace,
AffineWorkspace,
LocalWorkspace, LocalWorkspace,
} from '@affine/workspace/type'; } from '@affine/workspace/type';
import type { Workspace } from '@blocksuite/store'; import type { Workspace } from '@blocksuite/store';
@@ -15,7 +15,11 @@ import { avatarImageStyle, avatarStyle } from './index.css';
export type WorkspaceAvatarProps = { export type WorkspaceAvatarProps = {
size?: number; size?: number;
workspace: AffineWorkspace | LocalWorkspace | AffinePublicWorkspace | null; workspace:
| AffineLegacyCloudWorkspace
| LocalWorkspace
| AffinePublicWorkspace
| null;
className?: string; className?: string;
}; };

View File

@@ -1,6 +1,9 @@
import { useAFFiNEI18N } from '@affine/i18n/hooks'; import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { PermissionType } from '@affine/workspace/affine/api'; import { PermissionType } from '@affine/workspace/affine/api';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { SettingsIcon } from '@blocksuite/icons'; import { SettingsIcon } from '@blocksuite/icons';
import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name';
@@ -16,7 +19,7 @@ import {
} from './styles'; } from './styles';
export type WorkspaceTypeProps = { export type WorkspaceTypeProps = {
workspace: AffineWorkspace | LocalWorkspace; workspace: AffineLegacyCloudWorkspace | LocalWorkspace;
}; };
import { import {
@@ -78,9 +81,11 @@ const WorkspaceType: FC<WorkspaceTypeProps> = ({ workspace }) => {
export type WorkspaceCardProps = { export type WorkspaceCardProps = {
currentWorkspaceId: string | null; currentWorkspaceId: string | null;
workspace: AffineWorkspace | LocalWorkspace; workspace: AffineLegacyCloudWorkspace | LocalWorkspace;
onClick: (workspace: AffineWorkspace | LocalWorkspace) => void; onClick: (workspace: AffineLegacyCloudWorkspace | LocalWorkspace) => void;
onSettingClick: (workspace: AffineWorkspace | LocalWorkspace) => void; onSettingClick: (
workspace: AffineLegacyCloudWorkspace | LocalWorkspace
) => void;
}; };
export const WorkspaceCard: FC<WorkspaceCardProps> = ({ export const WorkspaceCard: FC<WorkspaceCardProps> = ({

View File

@@ -1,4 +1,7 @@
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import type { DragEndEvent } from '@dnd-kit/core'; import type { DragEndEvent } from '@dnd-kit/core';
import { import {
DndContext, DndContext,
@@ -14,15 +17,17 @@ import { WorkspaceCard } from '../workspace-card';
export type WorkspaceListProps = { export type WorkspaceListProps = {
disabled?: boolean; disabled?: boolean;
currentWorkspaceId: string | null; currentWorkspaceId: string | null;
items: (AffineWorkspace | LocalWorkspace)[]; items: (AffineLegacyCloudWorkspace | LocalWorkspace)[];
onClick: (workspace: AffineWorkspace | LocalWorkspace) => void; onClick: (workspace: AffineLegacyCloudWorkspace | LocalWorkspace) => void;
onSettingClick: (workspace: AffineWorkspace | LocalWorkspace) => void; onSettingClick: (
workspace: AffineLegacyCloudWorkspace | LocalWorkspace
) => void;
onDragEnd: (event: DragEndEvent) => void; onDragEnd: (event: DragEndEvent) => void;
}; };
const SortableWorkspaceItem: FC< const SortableWorkspaceItem: FC<
Omit<WorkspaceListProps, 'items'> & { Omit<WorkspaceListProps, 'items'> & {
item: AffineWorkspace | LocalWorkspace; item: AffineLegacyCloudWorkspace | LocalWorkspace;
} }
> = props => { > = props => {
const { setNodeRef, attributes, listeners, transform } = useSortable({ const { setNodeRef, attributes, listeners, transform } = useSortable({

View File

@@ -1,5 +1,8 @@
import { PermissionType, WorkspaceType } from '@affine/workspace/affine/api'; import { PermissionType, WorkspaceType } from '@affine/workspace/affine/api';
import type { AffineWorkspace, LocalWorkspace } from '@affine/workspace/type'; import type {
AffineLegacyCloudWorkspace,
LocalWorkspace,
} from '@affine/workspace/type';
import { WorkspaceFlavour } from '@affine/workspace/type'; import { WorkspaceFlavour } from '@affine/workspace/type';
import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils'; import { createEmptyBlockSuiteWorkspace } from '@affine/workspace/utils';
import type { Page } from '@blocksuite/store'; import type { Page } from '@blocksuite/store';
@@ -50,7 +53,7 @@ const localWorkspace: LocalWorkspace = {
providers: [], providers: [],
}; };
const affineWorkspace: AffineWorkspace = { const affineWorkspace: AffineLegacyCloudWorkspace = {
id: 'test-workspace', id: 'test-workspace',
flavour: WorkspaceFlavour.AFFINE, flavour: WorkspaceFlavour.AFFINE,
blockSuiteWorkspace, blockSuiteWorkspace,

View File

@@ -80,13 +80,16 @@ export interface AffineWebSocketProvider extends BackgroundProvider {
export type Provider = BackgroundProvider | NecessaryProvider; export type Provider = BackgroundProvider | NecessaryProvider;
export interface AffineWorkspace extends RemoteWorkspace { export interface AffineLegacyCloudWorkspace extends RemoteWorkspace {
flavour: WorkspaceFlavour.AFFINE; flavour: WorkspaceFlavour.AFFINE;
// empty // empty
blockSuiteWorkspace: BlockSuiteWorkspace; blockSuiteWorkspace: BlockSuiteWorkspace;
providers: Provider[]; providers: Provider[];
} }
// todo: update type with nest.js
export type AffineCloudWorkspace = LocalWorkspace;
export interface LocalWorkspace { export interface LocalWorkspace {
flavour: WorkspaceFlavour.LOCAL; flavour: WorkspaceFlavour.LOCAL;
id: string; id: string;
@@ -101,6 +104,12 @@ export interface AffinePublicWorkspace {
providers: Provider[]; providers: Provider[];
} }
export const enum ReleaseType {
// if workspace is not released yet, we will not show it in the workspace list
UNRELEASED = 'unreleased',
STABLE = 'stable',
}
export const enum LoadPriority { export const enum LoadPriority {
HIGH = 1, HIGH = 1,
MEDIUM = 2, MEDIUM = 2,
@@ -108,7 +117,18 @@ export const enum LoadPriority {
} }
export const enum WorkspaceFlavour { export const enum WorkspaceFlavour {
/**
* AFFiNE Workspace is the workspace
* that hosted on the Legacy AFFiNE Cloud Server.
*
* @deprecated
* We no longer maintain this kind of workspace, please use AFFiNE-Cloud instead.
*/
AFFINE = 'affine', AFFINE = 'affine',
/**
* New AFFiNE Cloud Workspace using Nest.js Server.
*/
AFFINE_CLOUD = 'affine-cloud',
LOCAL = 'local', LOCAL = 'local',
PUBLIC = 'affine-public', PUBLIC = 'affine-public',
} }
@@ -125,9 +145,11 @@ export type SettingPanel = (typeof settingPanel)[keyof typeof settingPanel];
// built-in workspaces // built-in workspaces
export interface WorkspaceRegistry { export interface WorkspaceRegistry {
[WorkspaceFlavour.AFFINE]: AffineWorkspace; [WorkspaceFlavour.AFFINE]: AffineLegacyCloudWorkspace;
[WorkspaceFlavour.LOCAL]: LocalWorkspace; [WorkspaceFlavour.LOCAL]: LocalWorkspace;
[WorkspaceFlavour.PUBLIC]: AffinePublicWorkspace; [WorkspaceFlavour.PUBLIC]: AffinePublicWorkspace;
// todo: update workspace type to new
[WorkspaceFlavour.AFFINE_CLOUD]: AffineCloudWorkspace;
} }
export interface WorkspaceCRUD<Flavour extends keyof WorkspaceRegistry> { export interface WorkspaceCRUD<Flavour extends keyof WorkspaceRegistry> {