refactor(infra): migrate to new infra (#5565)

This commit is contained in:
EYHN
2024-01-30 07:16:39 +00:00
parent 1e3499c323
commit 329fc19852
170 changed files with 2007 additions and 4354 deletions
+10 -6
View File
@@ -1,8 +1,9 @@
import { Menu } from '@affine/component/ui/menu';
import { WorkspaceFallback } from '@affine/component/workspace';
import { workspaceListAtom } from '@affine/core/modules/workspace';
import { WorkspaceSubPath } from '@affine/core/shared';
import { useAtomValue } from 'jotai';
import { WorkspaceManager } from '@toeverything/infra';
import { WorkspaceListService } from '@toeverything/infra';
import { useService } from '@toeverything/infra';
import { useLiveData } from '@toeverything/infra';
import { lazy, useEffect, useLayoutEffect, useState } from 'react';
import { type LoaderFunction, redirect } from 'react-router-dom';
@@ -10,6 +11,7 @@ import { createFirstAppData } from '../bootstrap/first-app-data';
import { UserWithWorkspaceList } from '../components/pure/workspace-slider-bar/user-with-workspace-list';
import { appConfigStorage } from '../hooks/use-app-config-storage';
import { useNavigateHelper } from '../hooks/use-navigate-helper';
import { WorkspaceSubPath } from '../shared';
const AllWorkspaceModals = lazy(() =>
import('../providers/modal-provider').then(({ AllWorkspaceModals }) => ({
@@ -29,7 +31,7 @@ export const Component = () => {
const [navigating, setNavigating] = useState(false);
const [creating, setCreating] = useState(false);
const list = useAtomValue(workspaceListAtom);
const list = useLiveData(useService(WorkspaceListService).workspaceList);
const { openPage } = useNavigateHelper();
useLayoutEffect(() => {
@@ -44,16 +46,18 @@ export const Component = () => {
setNavigating(true);
}, [list, openPage]);
const workspaceManager = useService(WorkspaceManager);
useEffect(() => {
setCreating(true);
createFirstAppData()
createFirstAppData(workspaceManager)
.catch(err => {
console.error('Failed to create first app data', err);
})
.finally(() => {
setCreating(false);
});
}, []);
}, [workspaceManager]);
if (navigating || creating) {
return <WorkspaceFallback></WorkspaceFallback>;
@@ -1,17 +1,27 @@
import { MainContainer } from '@affine/component/workspace';
import { usePageDocumentTitle } from '@affine/core/hooks/use-global-state';
import { DebugLogger } from '@affine/debug';
import { WorkspaceFlavour } from '@affine/env/workspace';
import { fetchWithTraceReport } from '@affine/graphql';
import { globalBlockSuiteSchema } from '@affine/workspace';
import {
createAffineCloudBlobStorage,
createStaticBlobStorage,
AffineCloudBlobStorage,
StaticBlobStorage,
} from '@affine/workspace-impl';
import { assertExists } from '@blocksuite/global/utils';
import { type Page, Workspace } from '@blocksuite/store';
import {
EmptyBlobStorage,
LocalBlobStorage,
LocalSyncStorage,
Page,
PageManager,
ReadonlyMappingSyncStorage,
RemoteBlobStorage,
useService,
useServiceOptional,
WorkspaceIdContext,
WorkspaceManager,
WorkspaceScope,
} from '@toeverything/infra';
import { noop } from 'foxact/noop';
import type { ReactElement } from 'react';
import { useCallback } from 'react';
import { useEffect } from 'react';
import type { LoaderFunction } from 'react-router-dom';
import {
isRouteErrorResponse,
@@ -19,12 +29,13 @@ import {
useLoaderData,
useRouteError,
} from 'react-router-dom';
import { applyUpdate } from 'yjs';
import type { PageMode } from '../../atoms';
import { AppContainer } from '../../components/affine/app-container';
import { PageDetailEditor } from '../../components/page-detail-editor';
import { SharePageNotFoundError } from '../../components/share-page-not-found-error';
import { CurrentPageService } from '../../modules/page';
import { CurrentWorkspaceService } from '../../modules/workspace';
import { ShareHeader } from './share-header';
type DocPublishMode = 'edgeless' | 'page';
@@ -57,8 +68,11 @@ export async function downloadBinaryFromCloud(
}
type LoaderData = {
page: Page;
pageId: string;
workspaceId: string;
publishMode: PageMode;
pageArrayBuffer: ArrayBuffer;
workspaceArrayBuffer: ArrayBuffer;
};
function assertDownloadResponse(
@@ -73,55 +87,104 @@ function assertDownloadResponse(
}
}
const logger = new DebugLogger('public:share-page');
export const loader: LoaderFunction = async ({ params }) => {
const workspaceId = params?.workspaceId;
const pageId = params?.pageId;
if (!workspaceId || !pageId) {
return redirect('/404');
}
const workspace = new Workspace({
id: workspaceId,
blobStorages: [
() => ({
crud: createAffineCloudBlobStorage(workspaceId),
}),
() => ({
crud: createStaticBlobStorage(),
}),
],
schema: globalBlockSuiteSchema,
});
// download root workspace
{
const response = await downloadBinaryFromCloud(workspaceId, workspaceId);
assertDownloadResponse(response);
const { arrayBuffer } = response;
applyUpdate(workspace.doc, new Uint8Array(arrayBuffer));
workspace.doc.emit('sync', []);
}
const page = workspace.getPage(pageId);
assertExists(page, 'cannot find page');
// download page
const response = await downloadBinaryFromCloud(
const [workspaceResponse, pageResponse] = await Promise.all([
downloadBinaryFromCloud(workspaceId, workspaceId),
downloadBinaryFromCloud(workspaceId, pageId),
]);
assertDownloadResponse(workspaceResponse);
const { arrayBuffer: workspaceArrayBuffer } = workspaceResponse;
assertDownloadResponse(pageResponse);
const { arrayBuffer: pageArrayBuffer, publishMode } = pageResponse;
return {
workspaceId,
page.spaceDoc.guid
);
assertDownloadResponse(response);
const { arrayBuffer, publishMode } = response;
applyUpdate(page.spaceDoc, new Uint8Array(arrayBuffer));
logger.info('workspace', workspace);
workspace.awarenessStore.setReadonly(page, true);
return { page, publishMode };
pageId,
publishMode,
workspaceArrayBuffer,
pageArrayBuffer,
} satisfies LoaderData;
};
export const Component = (): ReactElement => {
const { page, publishMode } = useLoaderData() as LoaderData;
usePageDocumentTitle(page.meta);
export const Component = () => {
const {
workspaceId,
pageId,
publishMode,
workspaceArrayBuffer,
pageArrayBuffer,
} = useLoaderData() as LoaderData;
const workspaceManager = useService(WorkspaceManager);
const currentWorkspace = useService(CurrentWorkspaceService);
useEffect(() => {
// create a workspace for share page
const workspace = workspaceManager.instantiate(
{
id: workspaceId,
flavour: WorkspaceFlavour.AFFINE_CLOUD,
},
services => {
services
.scope(WorkspaceScope)
.addImpl(LocalBlobStorage, EmptyBlobStorage)
.addImpl(RemoteBlobStorage('affine'), AffineCloudBlobStorage, [
WorkspaceIdContext,
])
.addImpl(RemoteBlobStorage('static'), StaticBlobStorage)
.addImpl(
LocalSyncStorage,
ReadonlyMappingSyncStorage({
[workspaceId]: new Uint8Array(workspaceArrayBuffer),
[pageId]: new Uint8Array(pageArrayBuffer),
})
);
}
);
workspace.engine.sync
.waitForSynced()
.then(() => {
const { page } = workspace.services
.get(PageManager)
.openByPageId(pageId);
workspace.blockSuiteWorkspace.awarenessStore.setReadonly(
page.blockSuitePage,
true
);
const currentPage = workspace.services.get(CurrentPageService);
currentWorkspace.openWorkspace(workspace);
currentPage.openPage(page);
})
.catch(err => {
console.error(err);
});
}, [
currentWorkspace,
pageArrayBuffer,
pageId,
workspaceArrayBuffer,
workspaceId,
workspaceManager,
]);
const page = useServiceOptional(Page);
usePageDocumentTitle(page?.meta);
if (!page) {
return;
}
return (
<AppContainer>
@@ -129,14 +192,14 @@ export const Component = (): ReactElement => {
<ShareHeader
pageId={page.id}
publishMode={publishMode}
blockSuiteWorkspace={page.workspace}
blockSuiteWorkspace={page.blockSuitePage.workspace}
/>
<PageDetailEditor
isPublic
publishMode={publishMode}
workspace={page.workspace}
workspace={page.blockSuitePage.workspace}
pageId={page.id}
onLoad={useCallback(() => noop, [])}
onLoad={() => noop}
/>
</MainContainer>
</AppContainer>
@@ -1,9 +1,9 @@
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { CollectionService } from '@affine/core/modules/collection';
import type { Collection, Filter } from '@affine/env/filter';
import { useAtomValue } from 'jotai';
import { useService } from '@toeverything/infra';
import { Workspace } from '@toeverything/infra';
import { useCallback } from 'react';
import { collectionsCRUDAtom } from '../../../atoms/collections';
import { filterContainerStyle } from '../../../components/filter-container.css';
import {
FilterList,
@@ -13,9 +13,9 @@ import {
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
export const FilterContainer = () => {
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const navigateHelper = useNavigateHelper();
const setting = useCollectionManager(collectionsCRUDAtom);
const setting = useCollectionManager(useService(CollectionService));
const saveToCollection = useCallback(
(collection: Collection) => {
setting.createCollection({
@@ -1,6 +1,5 @@
import { IconButton } from '@affine/component';
import type { AllPageFilterOption } from '@affine/core/atoms';
import { collectionsCRUDAtom } from '@affine/core/atoms/collections';
import {
CollectionList,
PageListNewPageButton,
@@ -13,9 +12,11 @@ import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-lis
import { useDeleteCollectionInfo } from '@affine/core/hooks/affine/use-delete-collection-info';
import { PlusIcon } from '@blocksuite/icons';
import type { Workspace } from '@blocksuite/store';
import { useService } from '@toeverything/infra/di';
import clsx from 'clsx';
import { useMemo } from 'react';
import { CollectionService } from '../../../modules/collection';
import * as styles from './all-page.css';
import { FilterContainer } from './all-page-filter';
@@ -32,7 +33,7 @@ export const AllPageHeader = ({
activeFilter: AllPageFilterOption;
onCreateCollection?: () => void;
}) => {
const setting = useCollectionManager(collectionsCRUDAtom);
const setting = useCollectionManager(useService(CollectionService));
const config = useAllPageListConfig();
const userInfo = useDeleteCollectionInfo();
const isWindowsDesktop = environment.isDesktop && environment.isWindows;
@@ -1,5 +1,4 @@
import type { AllPageFilterOption } from '@affine/core/atoms';
import { collectionsCRUDAtom } from '@affine/core/atoms/collections';
import { HubIsland } from '@affine/core/components/affine/hub-island';
import {
CollectionListHeader,
@@ -10,7 +9,6 @@ import {
useCollectionManager,
useEditCollectionName,
useFilteredPageMetas,
useSavedCollections,
useTagMetas,
VirtualizedCollectionList,
VirtualizedPageList,
@@ -22,15 +20,18 @@ import {
import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config';
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { performanceRenderLogger } from '@affine/core/shared';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { useAtomValue, useSetAtom } from 'jotai';
import { useService } from '@toeverything/infra';
import { useLiveData } from '@toeverything/infra';
import { Workspace } from '@toeverything/infra';
import { useSetAtom } from 'jotai';
import { nanoid } from 'nanoid';
import { useCallback, useEffect, useMemo, useState } from 'react';
import { useLocation, useParams } from 'react-router-dom';
import { NIL } from 'uuid';
import { CollectionService } from '../../../modules/collection';
import {
EmptyCollectionList,
EmptyPageList,
@@ -47,13 +48,14 @@ export const AllPage = ({
}) => {
const t = useAFFiNEI18N();
const params = useParams();
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const pageMetas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
const [hideHeaderCreateNew, setHideHeaderCreateNew] = useState(true);
const setting = useCollectionManager(collectionsCRUDAtom);
const collectionService = useService(CollectionService);
const collections = useLiveData(collectionService.collections);
const setting = useCollectionManager(collectionService);
const config = useAllPageListConfig();
const { collections } = useSavedCollections(collectionsCRUDAtom);
const { tags, tagMetas, filterPageMetaByTag, deleteTags } = useTagMetas(
currentWorkspace.blockSuiteWorkspace,
pageMetas
@@ -212,7 +214,7 @@ export const AllPage = ({
export const Component = () => {
performanceRenderLogger.info('AllPage');
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const currentCollection = useSetAtom(currentCollectionAtom);
const navigateHelper = useNavigateHelper();
@@ -12,7 +12,7 @@ import {
import { WindowsAppControls } from '@affine/core/components/pure/header/windows-app-controls';
import { useAllPageListConfig } from '@affine/core/hooks/affine/use-all-page-list-config';
import { useAsyncCallback } from '@affine/core/hooks/affine-async-hooks';
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { CollectionService } from '@affine/core/modules/collection';
import type { Collection } from '@affine/env/filter';
import { Trans } from '@affine/i18n';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
@@ -22,19 +22,17 @@ import {
PageIcon,
ViewLayersIcon,
} from '@blocksuite/icons';
import { Workspace } from '@toeverything/infra';
import { getCurrentStore } from '@toeverything/infra/atom';
import { useService } from '@toeverything/infra/di';
import { useLiveData } from '@toeverything/infra/livedata';
import { useAtomValue } from 'jotai';
import { useSetAtom } from 'jotai';
import { useCallback, useEffect, useState } from 'react';
import { type LoaderFunction, redirect, useParams } from 'react-router-dom';
import {
collectionsCRUDAtom,
pageCollectionBaseAtom,
} from '../../atoms/collections';
import { useNavigateHelper } from '../../hooks/use-navigate-helper';
import { WorkspaceSubPath } from '../../shared';
import { getWorkspaceSetting } from '../../utils/workspace-setting';
import { AllPage } from './all-page/all-page';
import * as styles from './collection.css';
@@ -48,18 +46,19 @@ export const loader: LoaderFunction = async args => {
};
export const Component = function CollectionPage() {
const { collections, loading } = useAtomValue(pageCollectionBaseAtom);
const collectionService = useService(CollectionService);
const collections = useLiveData(collectionService.collections);
const navigate = useNavigateHelper();
const params = useParams();
const workspace = useAtomValue(waitForCurrentWorkspaceAtom);
const workspace = useService(Workspace);
const collection = collections.find(v => v.id === params.collectionId);
const pushNotification = useSetAtom(pushNotificationAtom);
useEffect(() => {
if (!loading && !collection) {
if (!collection) {
navigate.jumpToSubPath(workspace.id, WorkspaceSubPath.ALL);
const collection = getWorkspaceSetting(
workspace.blockSuiteWorkspace
).collectionsTrash.find(v => v.collection.id === params.collectionId);
const collection = collectionService.collectionsTrash.value.find(
v => v.collection.id === params.collectionId
);
let text = 'Collection is not exist';
if (collection) {
if (collection.userId) {
@@ -75,21 +74,18 @@ export const Component = function CollectionPage() {
}
}, [
collection,
loading,
collectionService.collectionsTrash.value,
navigate,
params.collectionId,
pushNotification,
workspace.blockSuiteWorkspace,
workspace.id,
]);
if (loading) {
return null;
}
if (!collection) {
return null;
}
return isEmpty(collection) ? (
<Placeholder collection={collection} workspaceId={workspace.id} />
<Placeholder collection={collection} />
) : (
<AllPage activeFilter="collections" />
);
@@ -97,24 +93,19 @@ export const Component = function CollectionPage() {
const isWindowsDesktop = environment.isDesktop && environment.isWindows;
const Placeholder = ({
collection,
workspaceId,
}: {
collection: Collection;
workspaceId: string;
}) => {
const { updateCollection } = useCollectionManager(collectionsCRUDAtom);
const Placeholder = ({ collection }: { collection: Collection }) => {
const workspace = useService(Workspace);
const collectionService = useCollectionManager(useService(CollectionService));
const { node, open } = useEditCollection(useAllPageListConfig());
const { jumpToCollections } = useNavigateHelper();
const openPageEdit = useAsyncCallback(async () => {
const ret = await open({ ...collection }, 'page');
updateCollection(ret);
}, [open, collection, updateCollection]);
collectionService.updateCollection(ret);
}, [open, collection, collectionService]);
const openRuleEdit = useAsyncCallback(async () => {
const ret = await open({ ...collection }, 'rule');
updateCollection(ret);
}, [collection, open, updateCollection]);
collectionService.updateCollection(ret);
}, [collection, open, collectionService]);
const [showTips, setShowTips] = useState(false);
useEffect(() => {
setShowTips(!localStorage.getItem('hide-empty-collection-help-info'));
@@ -127,8 +118,8 @@ const Placeholder = ({
const leftSidebarOpen = useAtomValue(appSidebarOpenAtom);
const handleJumpToCollections = useCallback(() => {
jumpToCollections(workspaceId);
}, [jumpToCollections, workspaceId]);
jumpToCollections(workspace.id);
}, [jumpToCollections, workspace]);
return (
<div
@@ -11,9 +11,9 @@ import { JournalTodayButton } from '@affine/core/components/blocksuite/block-sui
import { PageHeaderMenuButton } from '@affine/core/components/blocksuite/block-suite-header/menu';
import { EditorModeSwitch } from '@affine/core/components/blocksuite/block-suite-mode-switch';
import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import type { Workspace } from '@affine/workspace';
import { RightSidebarIcon } from '@blocksuite/icons';
import type { Page } from '@blocksuite/store';
import type { Workspace } from '@toeverything/infra';
import { useAtomValue, useSetAtom } from 'jotai';
import { useCallback, useRef } from 'react';
@@ -1,18 +1,24 @@
import { PageDetailSkeleton } from '@affine/component/page-detail-skeleton';
import { ResizePanel } from '@affine/component/resize-panel';
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { useWorkspaceStatus } from '@affine/core/hooks/use-workspace-status';
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { WorkspaceSubPath } from '@affine/core/shared';
import { globalBlockSuiteSchema, SyncEngineStep } from '@affine/workspace';
import { CollectionService } from '@affine/core/modules/collection';
import {
BookmarkService,
customImageProxyMiddleware,
ImageService,
} from '@blocksuite/blocks';
import type { AffineEditorContainer } from '@blocksuite/presets';
import type { Page, Workspace } from '@blocksuite/store';
import { appSettingAtom } from '@toeverything/infra/atom';
import type { Page as BlockSuitePage } from '@blocksuite/store';
import {
globalBlockSuiteSchema,
Page,
PageListService,
PageManager,
useLiveData,
useServiceOptional,
} from '@toeverything/infra';
import { appSettingAtom, Workspace } from '@toeverything/infra';
import { useService } from '@toeverything/infra';
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
import {
memo,
@@ -20,13 +26,12 @@ import {
type ReactNode,
useCallback,
useEffect,
useState,
useMemo,
} from 'react';
import { useParams } from 'react-router-dom';
import type { Map as YMap } from 'yjs';
import { setPageModeAtom } from '../../../atoms';
import { collectionsCRUDAtom } from '../../../atoms/collections';
import { currentModeAtom, currentPageIdAtom } from '../../../atoms/mode';
import { AffineErrorBoundary } from '../../../components/affine/affine-error-boundary';
import { HubIsland } from '../../../components/affine/hub-island';
@@ -42,7 +47,8 @@ import { TopTip } from '../../../components/top-tip';
import { useRegisterBlocksuiteEditorCommands } from '../../../hooks/affine/use-register-blocksuite-editor-commands';
import { usePageDocumentTitle } from '../../../hooks/use-global-state';
import { useNavigateHelper } from '../../../hooks/use-navigate-helper';
import { performanceRenderLogger } from '../../../shared';
import { CurrentPageService } from '../../../modules/page';
import { performanceRenderLogger, WorkspaceSubPath } from '../../../shared';
import { PageNotFound } from '../../404';
import * as styles from './detail-page.css';
import { DetailPageHeader, RightSidebarHeader } from './detail-page-header';
@@ -104,10 +110,11 @@ const DetailPageLayout = ({
);
};
const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
const DetailPageImpl = memo(function DetailPageImpl() {
const page = useService(Page);
const currentPageId = page.id;
const { openPage, jumpToSubPath } = useNavigateHelper();
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace;
const pageMeta = useBlockSuitePageMeta(blockSuiteWorkspace).find(
@@ -116,14 +123,15 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
const isInTrash = pageMeta?.trash;
const { setTemporaryFilter } = useCollectionManager(collectionsCRUDAtom);
const collectionService = useService(CollectionService);
const { setTemporaryFilter } = useCollectionManager(collectionService);
const mode = useAtomValue(currentModeAtom);
const setPageMode = useSetAtom(setPageModeAtom);
useRegisterBlocksuiteEditorCommands(currentPageId, mode);
usePageDocumentTitle(pageMeta);
const onLoad = useCallback(
(page: Page, editor: AffineEditorContainer) => {
(page: BlockSuitePage, editor: AffineEditorContainer) => {
try {
// todo(joooye34): improve the following migration code
const surfaceBlock = page.getBlockByFlavour('affine:surface')[0];
@@ -182,7 +190,7 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
header={
<>
<DetailPageHeader
page={page}
page={page.blockSuitePage}
workspace={currentWorkspace}
showSidebarSwitch={!isInTrash}
/>
@@ -206,8 +214,14 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
sidebar={
!isInTrash ? (
<div className={styles.sidebarContainerInner}>
<RightSidebarHeader workspace={currentWorkspace} page={page} />
<EditorSidebar workspace={blockSuiteWorkspace} page={page} />
<RightSidebarHeader
workspace={currentWorkspace}
page={page.blockSuitePage}
/>
<EditorSidebar
workspace={blockSuiteWorkspace}
page={page.blockSuitePage}
/>
</div>
) : null
}
@@ -221,38 +235,44 @@ const DetailPageImpl = memo(function DetailPageImpl({ page }: { page: Page }) {
);
});
const useForceUpdate = () => {
const [, setCount] = useState(0);
return useCallback(() => setCount(count => count + 1), []);
};
const useSafePage = (workspace: Workspace, pageId: string) => {
const forceUpdate = useForceUpdate();
useEffect(() => {
const disposable = workspace.slots.pagesUpdated.on(() => {
forceUpdate();
});
return disposable.dispose;
}, [pageId, workspace.slots.pagesUpdated, forceUpdate]);
return workspace.getPage(pageId);
};
export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentSyncEngineStep = useWorkspaceStatus(
currentWorkspace,
s => s.engine.sync.step
const pageListService = useService(PageListService);
const pageListReady = useLiveData(pageListService.isReady);
const pageMetas = useLiveData(pageListService.pages);
const pageMeta = useMemo(
() => pageMetas.find(page => page.id === pageId),
[pageMetas, pageId]
);
const pageManager = useService(PageManager);
const currentPageService = useService(CurrentPageService);
useEffect(() => {
if (!pageMeta) {
return;
}
const { page, release } = pageManager.open(pageMeta);
currentPageService.openPage(page);
return () => {
currentPageService.closePage();
release();
};
}, [currentPageService, pageManager, pageMeta]);
const page = useServiceOptional(Page);
const currentWorkspace = useService(Workspace);
// set sync engine priority target
useEffect(() => {
currentWorkspace.setPriorityRule(id => id.endsWith(pageId));
}, [pageId, currentWorkspace]);
const page = useSafePage(currentWorkspace?.blockSuiteWorkspace, pageId);
// if sync engine has been synced and the page is null, show 404 page.
if (currentSyncEngineStep === SyncEngineStep.Synced && !page) {
if (pageListReady && !page) {
return <PageNotFound />;
}
@@ -266,7 +286,7 @@ export const DetailPage = ({ pageId }: { pageId: string }): ReactElement => {
});
}
return <DetailPageImpl page={page} />;
return <DetailPageImpl />;
};
export const Component = () => {
@@ -2,8 +2,8 @@ import { IconButton } from '@affine/component';
import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import { useWorkspaceEnabledFeatures } from '@affine/core/hooks/use-workspace-features';
import { FeatureType } from '@affine/graphql';
import type { Workspace } from '@affine/workspace/workspace';
import type { Page } from '@blocksuite/store';
import type { Workspace } from '@toeverything/infra';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import { useAtom, useAtomValue } from 'jotai';
import { useEffect } from 'react';
@@ -1,18 +1,18 @@
import { WorkspaceFallback } from '@affine/component/workspace';
import { useWorkspace } from '@affine/core/hooks/use-workspace';
import {
currentWorkspaceAtom,
workspaceListAtom,
workspaceListLoadingStatusAtom,
workspaceManagerAtom,
} from '@affine/core/modules/workspace';
import { type Workspace } from '@affine/workspace';
import { useAtom, useAtomValue } from 'jotai';
Workspace,
WorkspaceListService,
WorkspaceManager,
} from '@toeverything/infra';
import { useService, useServiceOptional } from '@toeverything/infra/di';
import { useLiveData } from '@toeverything/infra/livedata';
import { type ReactElement, Suspense, useEffect, useMemo } from 'react';
import { Outlet, useParams } from 'react-router-dom';
import { AffineErrorBoundary } from '../../components/affine/affine-error-boundary';
import { WorkspaceLayout } from '../../layouts/workspace-layout';
import { CurrentWorkspaceService } from '../../modules/workspace/current-workspace';
import { performanceRenderLogger } from '../../shared';
import { PageNotFound } from '../404';
@@ -30,29 +30,27 @@ declare global {
export const Component = (): ReactElement => {
performanceRenderLogger.info('WorkspaceLayout');
const [
_ /* read this atom here to make sure children refresh when currentWorkspace changed */,
setCurrentWorkspace,
] = useAtom(currentWorkspaceAtom);
const currentWorkspaceService = useService(CurrentWorkspaceService);
const params = useParams();
const list = useAtomValue(workspaceListAtom);
const listLoading = useAtomValue(workspaceListLoadingStatusAtom);
const workspaceManager = useAtomValue(workspaceManagerAtom);
const { workspaceList, loading: listLoading } = useLiveData(
useService(WorkspaceListService).status
);
const workspaceManager = useService(WorkspaceManager);
const meta = useMemo(() => {
return list.find(({ id }) => id === params.workspaceId);
}, [list, params.workspaceId]);
return workspaceList.find(({ id }) => id === params.workspaceId);
}, [workspaceList, params.workspaceId]);
const workspace = useWorkspace(meta);
useEffect(() => {
if (!workspace) {
setCurrentWorkspace(null);
currentWorkspaceService.closeWorkspace();
return undefined;
}
setCurrentWorkspace(workspace);
currentWorkspaceService.openWorkspace(workspace ?? null);
// for debug purpose
window.currentWorkspace = workspace;
@@ -65,14 +63,16 @@ export const Component = (): ReactElement => {
);
localStorage.setItem('last_workspace_id', workspace.id);
}, [setCurrentWorkspace, meta, workspaceManager, workspace]);
}, [meta, workspaceManager, workspace, currentWorkspaceService]);
const currentWorkspace = useServiceOptional(Workspace);
// if listLoading is false, we can show 404 page, otherwise we should show loading page.
if (listLoading === false && meta === undefined) {
return <PageNotFound />;
}
if (!workspace) {
if (!currentWorkspace) {
return <WorkspaceFallback key="workspaceLoading" />;
}
@@ -1,7 +1,6 @@
import { TagListHeader, useTagMetas } from '@affine/core/components/page-list';
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { useAtomValue } from 'jotai';
import { useService, Workspace } from '@toeverything/infra';
import { useMemo } from 'react';
import { type LoaderFunction, redirect, useParams } from 'react-router-dom';
@@ -19,7 +18,7 @@ export const loader: LoaderFunction = async args => {
export const Component = function TagPage() {
const params = useParams();
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const pageMetas = useBlockSuitePageMeta(currentWorkspace.blockSuiteWorkspace);
const { tagUsageCounts } = useTagMetas(
currentWorkspace.blockSuiteWorkspace,
@@ -14,13 +14,13 @@ import { Header } from '@affine/core/components/pure/header';
import { WindowsAppControls } from '@affine/core/components/pure/header/windows-app-controls';
import { useBlockSuiteMetaHelper } from '@affine/core/hooks/affine/use-block-suite-meta-helper';
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { waitForCurrentWorkspaceAtom } from '@affine/core/modules/workspace';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import { assertExists } from '@blocksuite/global/utils';
import { DeleteIcon } from '@blocksuite/icons';
import type { PageMeta } from '@blocksuite/store';
import { Workspace } from '@toeverything/infra';
import { getCurrentStore } from '@toeverything/infra/atom';
import { useAtomValue } from 'jotai';
import { useService } from '@toeverything/infra/di';
import { useCallback } from 'react';
import { type LoaderFunction } from 'react-router-dom';
import { NIL } from 'uuid';
@@ -61,7 +61,7 @@ export const loader: LoaderFunction = async () => {
};
export const TrashPage = () => {
const currentWorkspace = useAtomValue(waitForCurrentWorkspaceAtom);
const currentWorkspace = useService(Workspace);
const blockSuiteWorkspace = currentWorkspace.blockSuiteWorkspace;
assertExists(blockSuiteWorkspace);