fix(core): avoid page full refresh (#3341)

Co-authored-by: Peng Xiao <pengxiao@outlook.com>
This commit is contained in:
Alex Yang
2023-07-24 02:02:35 -07:00
committed by GitHub
parent ccb0df10e4
commit e6e98975ed
18 changed files with 276 additions and 433 deletions
+26 -74
View File
@@ -1,12 +1,10 @@
import { DebugLogger } from '@affine/debug';
import { WorkspaceSubPath } from '@affine/env/workspace';
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import { getWorkspace } from '@toeverything/plugin-infra/__internal__/workspace';
import { useAtomValue } from 'jotai';
import { lazy, useEffect, useRef } from 'react';
import { RouteLogic, useNavigateHelper } from '../hooks/use-navigate-helper';
import { useWorkspace } from '../hooks/use-workspace';
import { rootStore } from '@toeverything/plugin-infra/manager';
import { lazy } from 'react';
import type { LoaderFunction } from 'react-router-dom';
import { redirect } from 'react-router-dom';
const AllWorkspaceModals = lazy(() =>
import('../providers/modal-provider').then(({ AllWorkspaceModals }) => ({
@@ -14,81 +12,35 @@ const AllWorkspaceModals = lazy(() =>
}))
);
type WorkspaceLoaderProps = {
id: string;
};
const logger = new DebugLogger('index-page');
const WorkspaceLoader = (props: WorkspaceLoaderProps): null => {
useWorkspace(props.id);
export const loader: LoaderFunction = async () => {
const meta = await rootStore.get(rootWorkspacesMetadataAtom);
const lastId = localStorage.getItem('last_workspace_id');
const lastPageId = localStorage.getItem('last_page_id');
const target = (lastId && meta.find(({ id }) => id === lastId)) || meta.at(0);
if (target) {
const targetWorkspace = getWorkspace(target.id);
const nonTrashPages = targetWorkspace.meta.pageMetas.filter(
({ trash }) => !trash
);
const pageId =
nonTrashPages.find(({ id }) => id === lastPageId)?.id ??
nonTrashPages.at(0)?.id;
if (pageId) {
logger.debug('Found target workspace. Jump to page', pageId);
return redirect(`/workspace/${targetWorkspace.id}/${pageId}`);
} else {
logger.debug('Found target workspace. Jump to all page');
return redirect(`/workspace/${targetWorkspace.id}/all`);
}
}
return null;
};
const logger = new DebugLogger('index-page');
export const Component = () => {
const meta = useAtomValue(rootWorkspacesMetadataAtom);
const navigateHelper = useNavigateHelper();
const jumpOnceRef = useRef(false);
useEffect(() => {
if (jumpOnceRef.current) {
return;
}
const lastId = localStorage.getItem('last_workspace_id');
const lastPageId = localStorage.getItem('last_page_id');
const target =
(lastId && meta.find(({ id }) => id === lastId)) || meta.at(0);
if (target) {
const targetWorkspace = getWorkspace(target.id);
const nonTrashPages = targetWorkspace.meta.pageMetas.filter(
({ trash }) => !trash
);
const pageId =
nonTrashPages.find(({ id }) => id === lastPageId)?.id ??
nonTrashPages.at(0)?.id;
if (pageId) {
logger.debug('Found target workspace. Jump to page', pageId);
navigateHelper.jumpToPage(
targetWorkspace.id,
pageId,
RouteLogic.REPLACE
);
jumpOnceRef.current = true;
} else {
const clearId = setTimeout(() => {
dispose.dispose();
logger.debug('Found target workspace. Jump to all pages');
navigateHelper.jumpToSubPath(
targetWorkspace.id,
WorkspaceSubPath.ALL,
RouteLogic.REPLACE
);
jumpOnceRef.current = true;
}, 1000);
const dispose = targetWorkspace.slots.pageAdded.once(pageId => {
clearTimeout(clearId);
navigateHelper.jumpToPage(
targetWorkspace.id,
pageId,
RouteLogic.REPLACE
);
jumpOnceRef.current = true;
});
return () => {
clearTimeout(clearId);
dispose.dispose();
jumpOnceRef.current = false;
};
}
} else {
console.warn('No workspace found');
}
return;
}, [meta, navigateHelper]);
return (
<>
{meta.map(({ id }) => (
<WorkspaceLoader id={id} key={id} />
))}
<AllWorkspaceModals />
</>
);
+42 -8
View File
@@ -1,15 +1,41 @@
import { useCollectionManager } from '@affine/component/page-list';
import { DEFAULT_HELLO_WORLD_PAGE_ID_SUFFIX } from '@affine/env/constant';
import { WorkspaceSubPath } from '@affine/env/workspace';
import { assertExists } from '@blocksuite/global/utils';
import { useCallback } from 'react';
import { getActiveBlockSuiteWorkspaceAtom } from '@toeverything/plugin-infra/__internal__/workspace';
import {
currentPageIdAtom,
rootStore,
} from '@toeverything/plugin-infra/manager';
import { useAtom } from 'jotai/react';
import { useCallback, useEffect } from 'react';
import type { LoaderFunction } from 'react-router-dom';
import { redirect } from 'react-router-dom';
import { getUIAdapter } from '../../adapters/workspace';
import { useCurrentWorkspace } from '../../hooks/current/use-current-workspace';
import { useNavigateHelper } from '../../hooks/use-navigate-helper';
import { WorkspaceLayout } from '../../layouts/workspace-layout';
const AllPage = () => {
export const loader: LoaderFunction = async args => {
const workspaceId = args.params.workspaceId;
assertExists(workspaceId);
const workspaceAtom = getActiveBlockSuiteWorkspaceAtom(workspaceId);
const workspace = await rootStore.get(workspaceAtom);
const page = workspace.getPage(
`${workspace.id}-${DEFAULT_HELLO_WORLD_PAGE_ID_SUFFIX}`
);
if (page && page.meta.jumpOnce) {
workspace.meta.setPageMeta(page.id, {
jumpOnce: false,
});
return redirect(`/workspace/${workspace.id}/${page.id}`);
}
return null;
};
export const AllPage = () => {
const { jumpToPage } = useNavigateHelper();
const [currentPageId, setCurrentPageId] = useAtom(currentPageIdAtom);
const [currentWorkspace] = useCurrentWorkspace();
const setting = useCollectionManager(currentWorkspace.id);
const onClickPage = useCallback(
@@ -23,6 +49,18 @@ const AllPage = () => {
},
[currentWorkspace, jumpToPage]
);
useEffect(() => {
const page = currentWorkspace.blockSuiteWorkspace.getPage(
`${currentWorkspace.blockSuiteWorkspace.id}-${DEFAULT_HELLO_WORLD_PAGE_ID_SUFFIX}`
);
if (page && page.meta.jumpOnce) {
currentWorkspace.blockSuiteWorkspace.meta.setPageMeta(page.id, {
jumpOnce: false,
});
setCurrentPageId(currentPageId);
jumpToPage(currentWorkspace.id, page.id);
}
}, [currentPageId, currentWorkspace, jumpToPage, setCurrentPageId]);
const { PageList, Header } = getUIAdapter(currentWorkspace.flavour);
return (
<>
@@ -42,9 +80,5 @@ const AllPage = () => {
};
export const Component = () => {
return (
<WorkspaceLayout>
<AllPage />
</WorkspaceLayout>
);
return <AllPage />;
};
+24 -10
View File
@@ -7,18 +7,21 @@ import { WorkspaceSubPath } from '@affine/env/workspace';
import type { EditorContainer } from '@blocksuite/editor';
import { assertExists } from '@blocksuite/global/utils';
import type { Page } from '@blocksuite/store';
import { currentPageIdAtom } from '@toeverything/plugin-infra/manager';
import {
currentPageIdAtom,
rootStore,
} from '@toeverything/plugin-infra/manager';
import { useAtomValue } from 'jotai';
import { useAtom } from 'jotai/react';
import { type ReactElement, useCallback, useEffect } from 'react';
import type { LoaderFunction } from 'react-router-dom';
import { useLocation, useNavigate, useParams } from 'react-router-dom';
import { getUIAdapter } from '../../adapters/workspace';
import { useCurrentWorkspace } from '../../hooks/current/use-current-workspace';
import { useNavigateHelper } from '../../hooks/use-navigate-helper';
import { WorkspaceLayout } from '../../layouts/workspace-layout';
const WorkspaceDetailPageImpl = (): ReactElement => {
const DetailPageImpl = (): ReactElement => {
const { openPage, jumpToSubPath } = useNavigateHelper();
const currentPageId = useAtomValue(currentPageIdAtom);
const [currentWorkspace] = useCurrentWorkspace();
@@ -68,7 +71,7 @@ const WorkspaceDetailPageImpl = (): ReactElement => {
);
};
const WorkspaceDetailPage = (): ReactElement => {
export const DetailPage = (): ReactElement => {
const { workspaceId, pageId } = useParams();
const location = useLocation();
const navigate = useNavigate();
@@ -92,6 +95,13 @@ const WorkspaceDetailPage = (): ReactElement => {
currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
if (!page) {
navigate('/404');
} else {
// fixme: cleanup jumpOnce in the right time
if (page.meta.jumpOnce) {
currentWorkspace.blockSuiteWorkspace.setPageMeta(currentPageId, {
jumpOnce: false,
});
}
}
}
}
@@ -110,13 +120,17 @@ const WorkspaceDetailPage = (): ReactElement => {
if (!currentPageId || !page) {
return <PageDetailSkeleton key="current-page-is-null" />;
}
return <WorkspaceDetailPageImpl />;
return <DetailPageImpl />;
};
export const loader: LoaderFunction = args => {
if (args.params.pageId) {
localStorage.setItem('last_page_id', args.params.pageId);
rootStore.set(currentPageIdAtom, args.params.pageId);
}
return null;
};
export const Component = () => {
return (
<WorkspaceLayout>
<WorkspaceDetailPage />
</WorkspaceLayout>
);
return <DetailPage />;
};
+29
View File
@@ -0,0 +1,29 @@
import { rootWorkspacesMetadataAtom } from '@affine/workspace/atom';
import {
currentWorkspaceIdAtom,
rootStore,
} from '@toeverything/plugin-infra/manager';
import type { ReactElement } from 'react';
import { type LoaderFunction, Outlet, redirect } from 'react-router-dom';
import { WorkspaceLayout } from '../../layouts/workspace-layout';
export const loader: LoaderFunction = async args => {
const meta = await rootStore.get(rootWorkspacesMetadataAtom);
if (!meta.some(({ id }) => id === args.params.workspaceId)) {
return redirect('/404');
}
if (args.params.workspaceId) {
localStorage.setItem('last_workspace_id', args.params.workspaceId);
rootStore.set(currentWorkspaceIdAtom, args.params.workspaceId);
}
return null;
};
export const Component = (): ReactElement => {
return (
<WorkspaceLayout>
<Outlet />
</WorkspaceLayout>
);
};
+2 -7
View File
@@ -6,9 +6,8 @@ import { getUIAdapter } from '../../adapters/workspace';
import { BlockSuitePageList } from '../../components/blocksuite/block-suite-page-list';
import { useCurrentWorkspace } from '../../hooks/current/use-current-workspace';
import { useNavigateHelper } from '../../hooks/use-navigate-helper';
import { WorkspaceLayout } from '../../layouts/workspace-layout';
const TrashPage = () => {
export const TrashPage = () => {
const { jumpToPage } = useNavigateHelper();
const [currentWorkspace] = useCurrentWorkspace();
const onClickPage = useCallback(
@@ -44,9 +43,5 @@ const TrashPage = () => {
};
export const Component = () => {
return (
<WorkspaceLayout>
<TrashPage />
</WorkspaceLayout>
);
return <TrashPage />;
};