mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
fix: correct router logic (#2342)
This commit is contained in:
@@ -5,11 +5,7 @@ import 'fake-indexeddb/auto';
|
|||||||
|
|
||||||
import assert from 'node:assert';
|
import assert from 'node:assert';
|
||||||
|
|
||||||
import {
|
import { rootCurrentWorkspaceIdAtom } from '@affine/workspace/atom';
|
||||||
rootCurrentWorkspaceIdAtom,
|
|
||||||
rootWorkspacesMetadataAtom,
|
|
||||||
} from '@affine/workspace/atom';
|
|
||||||
import type { LocalWorkspace } from '@affine/workspace/type';
|
|
||||||
import { WorkspaceFlavour } from '@affine/workspace/type';
|
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||||
import type { PageBlockModel } from '@blocksuite/blocks';
|
import type { PageBlockModel } from '@blocksuite/blocks';
|
||||||
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||||
@@ -21,23 +17,17 @@ import {
|
|||||||
usePageMetaHelper,
|
usePageMetaHelper,
|
||||||
} from '@toeverything/hooks/use-block-suite-page-meta';
|
} from '@toeverything/hooks/use-block-suite-page-meta';
|
||||||
import { createStore, Provider } from 'jotai';
|
import { createStore, Provider } from 'jotai';
|
||||||
import { useRouter } from 'next/router';
|
|
||||||
import routerMock from 'next-router-mock';
|
import routerMock from 'next-router-mock';
|
||||||
import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
|
import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
|
||||||
import type React from 'react';
|
import type React from 'react';
|
||||||
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
import { currentWorkspaceIdAtom, workspacesAtom } from '../../atoms';
|
import { workspacesAtom } from '../../atoms';
|
||||||
import { LocalPlugin } from '../../plugins/local';
|
|
||||||
import { BlockSuiteWorkspace, WorkspaceSubPath } from '../../shared';
|
import { BlockSuiteWorkspace, WorkspaceSubPath } from '../../shared';
|
||||||
import {
|
import {
|
||||||
currentWorkspaceAtom,
|
currentWorkspaceAtom,
|
||||||
useCurrentWorkspace,
|
useCurrentWorkspace,
|
||||||
} from '../current/use-current-workspace';
|
} from '../current/use-current-workspace';
|
||||||
import {
|
|
||||||
useRecentlyViewed,
|
|
||||||
useSyncRecentViewsWithRouter,
|
|
||||||
} from '../use-recent-views';
|
|
||||||
import { useAppHelper, useWorkspaces } from '../use-workspaces';
|
import { useAppHelper, useWorkspaces } from '../use-workspaces';
|
||||||
|
|
||||||
vi.mock(
|
vi.mock(
|
||||||
@@ -223,58 +213,3 @@ describe('useWorkspaces', () => {
|
|||||||
expect(firstWorkspace.blockSuiteWorkspace.meta.name).toBe('test');
|
expect(firstWorkspace.blockSuiteWorkspace.meta.name).toBe('test');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('useRecentlyViewed', () => {
|
|
||||||
test('basic', async () => {
|
|
||||||
const { ProviderWrapper, store } = await getJotaiContext();
|
|
||||||
const workspaceId = blockSuiteWorkspace.id;
|
|
||||||
const pageId = 'page0';
|
|
||||||
store.set(rootWorkspacesMetadataAtom, [
|
|
||||||
{
|
|
||||||
id: workspaceId,
|
|
||||||
flavour: WorkspaceFlavour.LOCAL,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
LocalPlugin.CRUD.get = vi.fn().mockResolvedValue({
|
|
||||||
id: workspaceId,
|
|
||||||
flavour: WorkspaceFlavour.LOCAL,
|
|
||||||
blockSuiteWorkspace,
|
|
||||||
providers: [],
|
|
||||||
} satisfies LocalWorkspace);
|
|
||||||
store.set(currentWorkspaceIdAtom, blockSuiteWorkspace.id);
|
|
||||||
const workspace = await store.get(currentWorkspaceAtom);
|
|
||||||
expect(workspace?.id).toBe(blockSuiteWorkspace.id);
|
|
||||||
const currentHook = renderHook(() => useCurrentWorkspace(), {
|
|
||||||
wrapper: ProviderWrapper,
|
|
||||||
});
|
|
||||||
expect(currentHook.result.current[0]?.id).toEqual(workspaceId);
|
|
||||||
await store.get(currentWorkspaceAtom);
|
|
||||||
const recentlyViewedHook = renderHook(() => useRecentlyViewed(), {
|
|
||||||
wrapper: ProviderWrapper,
|
|
||||||
});
|
|
||||||
expect(recentlyViewedHook.result.current).toEqual([]);
|
|
||||||
const routerHook = renderHook(() => useRouter());
|
|
||||||
await routerHook.result.current.push({
|
|
||||||
pathname: '/workspace/[workspaceId]/[pageId]',
|
|
||||||
query: {
|
|
||||||
workspaceId,
|
|
||||||
pageId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
routerHook.rerender();
|
|
||||||
const syncHook = renderHook(
|
|
||||||
router => useSyncRecentViewsWithRouter(router, blockSuiteWorkspace),
|
|
||||||
{
|
|
||||||
wrapper: ProviderWrapper,
|
|
||||||
initialProps: routerHook.result.current,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
syncHook.rerender(routerHook.result.current);
|
|
||||||
expect(recentlyViewedHook.result.current).toEqual([
|
|
||||||
{
|
|
||||||
id: 'page0',
|
|
||||||
mode: 'page',
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
139
apps/web/src/hooks/__tests__/use-recent-views.spec.tsx
Normal file
139
apps/web/src/hooks/__tests__/use-recent-views.spec.tsx
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/**
|
||||||
|
* @vitest-environment happy-dom
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
rootCurrentWorkspaceIdAtom,
|
||||||
|
rootWorkspacesMetadataAtom,
|
||||||
|
} from '@affine/workspace/atom';
|
||||||
|
import type { LocalWorkspace } from '@affine/workspace/type';
|
||||||
|
import { WorkspaceFlavour } from '@affine/workspace/type';
|
||||||
|
import { __unstableSchemas, AffineSchemas } from '@blocksuite/blocks/models';
|
||||||
|
import type { Page } from '@blocksuite/store';
|
||||||
|
import { assertExists } from '@blocksuite/store';
|
||||||
|
import { renderHook } from '@testing-library/react';
|
||||||
|
import { createStore, Provider } from 'jotai/index';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
import routerMock from 'next-router-mock';
|
||||||
|
import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
|
||||||
|
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
||||||
|
|
||||||
|
import { workspacesAtom } from '../../atoms';
|
||||||
|
import { LocalPlugin } from '../../plugins/local';
|
||||||
|
import { BlockSuiteWorkspace } from '../../shared';
|
||||||
|
import { WorkspaceSubPath } from '../../shared';
|
||||||
|
import {
|
||||||
|
currentWorkspaceAtom,
|
||||||
|
useCurrentWorkspace,
|
||||||
|
} from '../current/use-current-workspace';
|
||||||
|
import {
|
||||||
|
useRecentlyViewed,
|
||||||
|
useSyncRecentViewsWithRouter,
|
||||||
|
} from '../use-recent-views';
|
||||||
|
|
||||||
|
let blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||||
|
beforeAll(() => {
|
||||||
|
routerMock.useParser(
|
||||||
|
createDynamicRouteParser([
|
||||||
|
`/workspace/[workspaceId/${WorkspaceSubPath.ALL}`,
|
||||||
|
`/workspace/[workspaceId/${WorkspaceSubPath.SETTING}`,
|
||||||
|
`/workspace/[workspaceId/${WorkspaceSubPath.TRASH}`,
|
||||||
|
`/workspace/[workspaceId/${WorkspaceSubPath.FAVORITE}`,
|
||||||
|
'/workspace/[workspaceId]/[pageId]',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
async function getJotaiContext() {
|
||||||
|
const store = createStore();
|
||||||
|
const ProviderWrapper: React.FC<React.PropsWithChildren> =
|
||||||
|
function ProviderWrapper({ children }) {
|
||||||
|
return <Provider store={store}>{children}</Provider>;
|
||||||
|
};
|
||||||
|
const workspaces = await store.get(workspacesAtom);
|
||||||
|
expect(workspaces.length).toBe(0);
|
||||||
|
return {
|
||||||
|
store,
|
||||||
|
ProviderWrapper,
|
||||||
|
initialWorkspaces: workspaces,
|
||||||
|
} as const;
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
blockSuiteWorkspace = new BlockSuiteWorkspace({ id: 'test' })
|
||||||
|
.register(AffineSchemas)
|
||||||
|
.register(__unstableSchemas);
|
||||||
|
const initPage = (page: Page) => {
|
||||||
|
expect(page).not.toBeNull();
|
||||||
|
assertExists(page);
|
||||||
|
const pageBlockId = page.addBlock('affine:page', {
|
||||||
|
title: new page.Text(''),
|
||||||
|
});
|
||||||
|
const frameId = page.addBlock('affine:frame', {}, pageBlockId);
|
||||||
|
page.addBlock('affine:paragraph', {}, frameId);
|
||||||
|
};
|
||||||
|
initPage(
|
||||||
|
blockSuiteWorkspace.createPage({
|
||||||
|
id: 'page0',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
initPage(blockSuiteWorkspace.createPage({ id: 'page1' }));
|
||||||
|
initPage(blockSuiteWorkspace.createPage({ id: 'page2' }));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('useRecentlyViewed', () => {
|
||||||
|
test('basic', async () => {
|
||||||
|
const { ProviderWrapper, store } = await getJotaiContext();
|
||||||
|
const workspaceId = blockSuiteWorkspace.id;
|
||||||
|
const pageId = 'page0';
|
||||||
|
store.set(rootWorkspacesMetadataAtom, [
|
||||||
|
{
|
||||||
|
id: workspaceId,
|
||||||
|
flavour: WorkspaceFlavour.LOCAL,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
LocalPlugin.CRUD.get = vi.fn().mockResolvedValue({
|
||||||
|
id: workspaceId,
|
||||||
|
flavour: WorkspaceFlavour.LOCAL,
|
||||||
|
blockSuiteWorkspace,
|
||||||
|
providers: [],
|
||||||
|
} satisfies LocalWorkspace);
|
||||||
|
store.set(rootCurrentWorkspaceIdAtom, blockSuiteWorkspace.id);
|
||||||
|
const workspace = await store.get(currentWorkspaceAtom);
|
||||||
|
expect(workspace?.id).toBe(blockSuiteWorkspace.id);
|
||||||
|
const currentHook = renderHook(() => useCurrentWorkspace(), {
|
||||||
|
wrapper: ProviderWrapper,
|
||||||
|
});
|
||||||
|
expect(currentHook.result.current[0]?.id).toEqual(workspaceId);
|
||||||
|
store.set(rootCurrentWorkspaceIdAtom, blockSuiteWorkspace.id);
|
||||||
|
await store.get(currentWorkspaceAtom);
|
||||||
|
const recentlyViewedHook = renderHook(() => useRecentlyViewed(), {
|
||||||
|
wrapper: ProviderWrapper,
|
||||||
|
});
|
||||||
|
expect(recentlyViewedHook.result.current).toEqual([]);
|
||||||
|
const routerHook = renderHook(() => useRouter(), {
|
||||||
|
wrapper: ProviderWrapper,
|
||||||
|
});
|
||||||
|
await routerHook.result.current.push({
|
||||||
|
pathname: '/workspace/[workspaceId]/[pageId]',
|
||||||
|
query: {
|
||||||
|
workspaceId,
|
||||||
|
pageId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
routerHook.rerender();
|
||||||
|
const syncHook = renderHook(
|
||||||
|
router => useSyncRecentViewsWithRouter(router, blockSuiteWorkspace),
|
||||||
|
{
|
||||||
|
wrapper: ProviderWrapper,
|
||||||
|
initialProps: routerHook.result.current,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
syncHook.rerender(routerHook.result.current);
|
||||||
|
expect(recentlyViewedHook.result.current).toEqual([
|
||||||
|
{
|
||||||
|
id: 'page0',
|
||||||
|
mode: 'page',
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
import { useAtomValue } from 'jotai';
|
|
||||||
|
|
||||||
import { lastWorkspaceIdAtom } from '../current/use-current-workspace';
|
|
||||||
|
|
||||||
export function useLastWorkspaceId() {
|
|
||||||
return useAtomValue(lastWorkspaceIdAtom);
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
import { useAtom, useAtomValue } from 'jotai';
|
||||||
import { atomWithStorage } from 'jotai/utils';
|
|
||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
import { currentPageIdAtom, currentWorkspaceIdAtom } from '../../atoms';
|
import { currentPageIdAtom, currentWorkspaceIdAtom } from '../../atoms';
|
||||||
@@ -11,11 +10,6 @@ import type { AllWorkspace } from '../../shared';
|
|||||||
*/
|
*/
|
||||||
export const currentWorkspaceAtom = rootCurrentWorkspaceAtom;
|
export const currentWorkspaceAtom = rootCurrentWorkspaceAtom;
|
||||||
|
|
||||||
export const lastWorkspaceIdAtom = atomWithStorage<string | null>(
|
|
||||||
'last_workspace_id',
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
export function useCurrentWorkspace(): [
|
export function useCurrentWorkspace(): [
|
||||||
AllWorkspace,
|
AllWorkspace,
|
||||||
(id: string | null) => void
|
(id: string | null) => void
|
||||||
@@ -23,16 +17,17 @@ export function useCurrentWorkspace(): [
|
|||||||
const currentWorkspace = useAtomValue(rootCurrentWorkspaceAtom);
|
const currentWorkspace = useAtomValue(rootCurrentWorkspaceAtom);
|
||||||
const [, setId] = useAtom(currentWorkspaceIdAtom);
|
const [, setId] = useAtom(currentWorkspaceIdAtom);
|
||||||
const [, setPageId] = useAtom(currentPageIdAtom);
|
const [, setPageId] = useAtom(currentPageIdAtom);
|
||||||
const setLast = useSetAtom(lastWorkspaceIdAtom);
|
|
||||||
return [
|
return [
|
||||||
currentWorkspace,
|
currentWorkspace,
|
||||||
useCallback(
|
useCallback(
|
||||||
(id: string | null) => {
|
(id: string | null) => {
|
||||||
|
if (typeof window !== 'undefined' && id) {
|
||||||
|
localStorage.setItem('last_workspace_id', id);
|
||||||
|
}
|
||||||
setPageId(null);
|
setPageId(null);
|
||||||
setLast(id);
|
|
||||||
setId(id);
|
setId(id);
|
||||||
},
|
},
|
||||||
[setId, setLast, setPageId]
|
[setId, setPageId]
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
|
||||||
import { rootCurrentPageIdAtom } from '@affine/workspace/atom';
|
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
|
||||||
import type { NextRouter } from 'next/router';
|
|
||||||
import { useRef } from 'react';
|
|
||||||
|
|
||||||
import { rootCurrentWorkspaceAtom } from '../atoms/root';
|
|
||||||
export const HALT_PROBLEM_TIMEOUT = 1000;
|
|
||||||
|
|
||||||
const logger = new DebugLogger('useRouterWithWorkspaceIdDefense');
|
|
||||||
|
|
||||||
export function useRouterAndWorkspaceWithPageIdDefense(router: NextRouter) {
|
|
||||||
const currentWorkspace = useAtomValue(rootCurrentWorkspaceAtom);
|
|
||||||
const [currentPageId, setCurrentPageId] = useAtom(rootCurrentPageIdAtom);
|
|
||||||
const timeoutRef = useRef<unknown | null>(null);
|
|
||||||
if (!router.isReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!timeoutRef.current) {
|
|
||||||
timeoutRef.current = setTimeout(() => {
|
|
||||||
if (currentPageId) {
|
|
||||||
const page =
|
|
||||||
currentWorkspace.blockSuiteWorkspace.getPage(currentPageId);
|
|
||||||
if (!page) {
|
|
||||||
const firstOne =
|
|
||||||
currentWorkspace.blockSuiteWorkspace.meta.pageMetas.at(0);
|
|
||||||
if (firstOne) {
|
|
||||||
logger.warn(
|
|
||||||
'cannot find page',
|
|
||||||
currentPageId,
|
|
||||||
'so redirect to',
|
|
||||||
firstOne.id
|
|
||||||
);
|
|
||||||
setCurrentPageId(firstOne.id);
|
|
||||||
void router.push({
|
|
||||||
pathname: '/workspace/[workspaceId]/[pageId]',
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId: currentWorkspace.id,
|
|
||||||
pageId: firstOne.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, HALT_PROBLEM_TIMEOUT);
|
|
||||||
}
|
|
||||||
const { workspaceId, pageId } = router.query;
|
|
||||||
if (typeof pageId !== 'string') {
|
|
||||||
console.warn('pageId is not a string', pageId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof workspaceId !== 'string') {
|
|
||||||
console.warn('workspaceId is not a string', workspaceId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (currentWorkspace?.id !== workspaceId) {
|
|
||||||
console.warn('workspaceId is not currentWorkspace', workspaceId);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (currentPageId !== pageId) {
|
|
||||||
console.log('set current page id', pageId);
|
|
||||||
setCurrentPageId(pageId);
|
|
||||||
void router.push({
|
|
||||||
pathname: '/workspace/[workspaceId]/[pageId]',
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId,
|
|
||||||
pageId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
|
||||||
import {
|
|
||||||
rootCurrentPageIdAtom,
|
|
||||||
rootCurrentWorkspaceIdAtom,
|
|
||||||
rootWorkspacesMetadataAtom,
|
|
||||||
} from '@affine/workspace/atom';
|
|
||||||
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
|
||||||
import type { NextRouter } from 'next/router';
|
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
const logger = new DebugLogger('useRouterWithWorkspaceIdDefense');
|
|
||||||
|
|
||||||
export function useRouterWithWorkspaceIdDefense(router: NextRouter) {
|
|
||||||
const metadata = useAtomValue(rootWorkspacesMetadataAtom);
|
|
||||||
const [currentWorkspaceId, setCurrentWorkspaceId] = useAtom(
|
|
||||||
rootCurrentWorkspaceIdAtom
|
|
||||||
);
|
|
||||||
const setCurrentPageId = useSetAtom(rootCurrentPageIdAtom);
|
|
||||||
const exist = useMemo(
|
|
||||||
() => metadata.find(m => m.id === currentWorkspaceId),
|
|
||||||
[currentWorkspaceId, metadata]
|
|
||||||
);
|
|
||||||
if (!router.isReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!currentWorkspaceId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!exist) {
|
|
||||||
console.warn('workspace not exist, redirect to first one');
|
|
||||||
// clean up
|
|
||||||
setCurrentWorkspaceId(null);
|
|
||||||
setCurrentPageId(null);
|
|
||||||
const firstOne = metadata.at(0);
|
|
||||||
if (!firstOne) {
|
|
||||||
throw new Error('no workspace');
|
|
||||||
}
|
|
||||||
logger.debug('redirect to', firstOne.id);
|
|
||||||
void router.push({
|
|
||||||
pathname: '/workspace/[workspaceId]/all',
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId: firstOne.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import { rootCurrentPageIdAtom } from '@affine/workspace/atom';
|
|
||||||
import { useAtom } from 'jotai';
|
|
||||||
import type { NextRouter } from 'next/router';
|
|
||||||
|
|
||||||
export function useSyncRouterWithCurrentPageId(router: NextRouter) {
|
|
||||||
const [currentPageId, setCurrentPageId] = useAtom(rootCurrentPageIdAtom);
|
|
||||||
if (!router.isReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const pageId = router.query.pageId;
|
|
||||||
if (currentPageId === pageId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (typeof pageId === 'string') {
|
|
||||||
console.log('set page id', pageId);
|
|
||||||
setCurrentPageId(pageId);
|
|
||||||
} else if (pageId === undefined) {
|
|
||||||
console.log('cleanup page');
|
|
||||||
setCurrentPageId(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
import { DebugLogger } from '@affine/debug';
|
|
||||||
import {
|
|
||||||
rootCurrentWorkspaceIdAtom,
|
|
||||||
rootWorkspacesMetadataAtom,
|
|
||||||
} from '@affine/workspace/atom';
|
|
||||||
import { useAtom, useAtomValue } from 'jotai';
|
|
||||||
import type { NextRouter } from 'next/router';
|
|
||||||
|
|
||||||
const logger = new DebugLogger('useSyncRouterWithCurrentWorkspaceId');
|
|
||||||
|
|
||||||
export function useSyncRouterWithCurrentWorkspaceId(router: NextRouter) {
|
|
||||||
const [currentWorkspaceId, setCurrentWorkspaceId] = useAtom(
|
|
||||||
rootCurrentWorkspaceIdAtom
|
|
||||||
);
|
|
||||||
const metadata = useAtomValue(rootWorkspacesMetadataAtom);
|
|
||||||
if (!router.isReady) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const workspaceId = router.query.workspaceId;
|
|
||||||
if (typeof workspaceId !== 'string') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (currentWorkspaceId === workspaceId) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (currentWorkspaceId) {
|
|
||||||
if (currentWorkspaceId !== workspaceId) {
|
|
||||||
const target = metadata.find(workspace => workspace.id === workspaceId);
|
|
||||||
logger.debug('workspace not exist, redirect to current one');
|
|
||||||
if (!target) {
|
|
||||||
// workspaceId is invalid, redirect to currentWorkspaceId
|
|
||||||
void router.push({
|
|
||||||
pathname: router.pathname,
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId: currentWorkspaceId,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const targetWorkspace = metadata.find(
|
|
||||||
workspace => workspace.id === workspaceId
|
|
||||||
);
|
|
||||||
if (targetWorkspace) {
|
|
||||||
console.log('set workspace id', workspaceId);
|
|
||||||
setCurrentWorkspaceId(targetWorkspace.id);
|
|
||||||
logger.debug('redirect to', targetWorkspace.id);
|
|
||||||
void router.push({
|
|
||||||
pathname: router.pathname,
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId: targetWorkspace.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const targetWorkspace = metadata.at(0);
|
|
||||||
if (targetWorkspace) {
|
|
||||||
console.log('set workspace id', workspaceId);
|
|
||||||
setCurrentWorkspaceId(targetWorkspace.id);
|
|
||||||
logger.debug('redirect to', targetWorkspace.id);
|
|
||||||
void router.push({
|
|
||||||
pathname: router.pathname,
|
|
||||||
query: {
|
|
||||||
...router.query,
|
|
||||||
workspaceId: targetWorkspace.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -39,9 +39,6 @@ import { RootAppSidebar } from '../components/root-app-sidebar';
|
|||||||
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../hooks/current/use-current-workspace';
|
||||||
import { useRouterHelper } from '../hooks/use-router-helper';
|
import { useRouterHelper } from '../hooks/use-router-helper';
|
||||||
import { useRouterTitle } from '../hooks/use-router-title';
|
import { useRouterTitle } from '../hooks/use-router-title';
|
||||||
import { useRouterWithWorkspaceIdDefense } from '../hooks/use-router-with-workspace-id-defense';
|
|
||||||
import { useSyncRouterWithCurrentPageId } from '../hooks/use-sync-router-with-current-page-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 { WorkspaceAdapters } from '../plugins';
|
import { WorkspaceAdapters } from '../plugins';
|
||||||
import { ModalProvider } from '../providers/modal-provider';
|
import { ModalProvider } from '../providers/modal-provider';
|
||||||
@@ -137,13 +134,21 @@ export const AllWorkspaceContext = ({
|
|||||||
export const CurrentWorkspaceContext = ({
|
export const CurrentWorkspaceContext = ({
|
||||||
children,
|
children,
|
||||||
}: PropsWithChildren): ReactElement => {
|
}: PropsWithChildren): ReactElement => {
|
||||||
const router = useRouter();
|
|
||||||
const workspaceId = useAtomValue(rootCurrentWorkspaceIdAtom);
|
const workspaceId = useAtomValue(rootCurrentWorkspaceIdAtom);
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
useSyncRouterWithCurrentPageId(router);
|
|
||||||
useRouterWithWorkspaceIdDefense(router);
|
|
||||||
const metadata = useAtomValue(rootWorkspacesMetadataAtom);
|
const metadata = useAtomValue(rootWorkspacesMetadataAtom);
|
||||||
const exist = metadata.find(m => m.id === workspaceId);
|
const exist = metadata.find(m => m.id === workspaceId);
|
||||||
|
const router = useRouter();
|
||||||
|
const push = router.push;
|
||||||
|
useEffect(() => {
|
||||||
|
const id = setTimeout(() => {
|
||||||
|
if (!exist) {
|
||||||
|
void push('/');
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
return () => {
|
||||||
|
clearTimeout(id);
|
||||||
|
};
|
||||||
|
}, [push, exist]);
|
||||||
if (!router.isReady) {
|
if (!router.isReady) {
|
||||||
return <WorkspaceFallback key="router-is-loading" />;
|
return <WorkspaceFallback key="router-is-loading" />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import { useRouter } from 'next/router';
|
|||||||
import { Suspense, useEffect } from 'react';
|
import { Suspense, useEffect } from 'react';
|
||||||
|
|
||||||
import { PageLoading } from '../components/pure/loading';
|
import { PageLoading } from '../components/pure/loading';
|
||||||
import { useLastWorkspaceId } from '../hooks/affine/use-last-leave-workspace-id';
|
|
||||||
import { RouteLogic, useRouterHelper } from '../hooks/use-router-helper';
|
import { RouteLogic, useRouterHelper } from '../hooks/use-router-helper';
|
||||||
import { useAppHelper, useWorkspaces } from '../hooks/use-workspaces';
|
import { useAppHelper, useWorkspaces } from '../hooks/use-workspaces';
|
||||||
import { WorkspaceSubPath } from '../shared';
|
import { WorkspaceSubPath } from '../shared';
|
||||||
@@ -15,16 +14,15 @@ const IndexPageInner = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const { jumpToPage, jumpToSubPath } = useRouterHelper(router);
|
const { jumpToPage, jumpToSubPath } = useRouterHelper(router);
|
||||||
const workspaces = useWorkspaces();
|
const workspaces = useWorkspaces();
|
||||||
const lastWorkspaceId = useLastWorkspaceId();
|
|
||||||
const helper = useAppHelper();
|
const helper = useAppHelper();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!router.isReady) {
|
if (!router.isReady) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const lastId = localStorage.getItem('last_workspace_id');
|
||||||
const targetWorkspace =
|
const targetWorkspace =
|
||||||
(lastWorkspaceId &&
|
(lastId && workspaces.find(({ id }) => id === lastId)) ||
|
||||||
workspaces.find(({ id }) => id === lastWorkspaceId)) ||
|
|
||||||
workspaces.at(0);
|
workspaces.at(0);
|
||||||
|
|
||||||
if (targetWorkspace) {
|
if (targetWorkspace) {
|
||||||
@@ -56,7 +54,7 @@ const IndexPageInner = () => {
|
|||||||
} else {
|
} else {
|
||||||
console.warn('No target workspace. This should not happen in production');
|
console.warn('No target workspace. This should not happen in production');
|
||||||
}
|
}
|
||||||
}, [helper, jumpToPage, jumpToSubPath, lastWorkspaceId, router, workspaces]);
|
}, [helper, jumpToPage, jumpToSubPath, router, workspaces]);
|
||||||
|
|
||||||
return <PageLoading key="IndexPageInfinitePageLoading" />;
|
return <PageLoading key="IndexPageInfinitePageLoading" />;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { useReferenceLinkEffect } from '../../../hooks/affine/use-reference-link
|
|||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
import { usePinboardHandler } from '../../../hooks/use-pinboard-handler';
|
import { usePinboardHandler } from '../../../hooks/use-pinboard-handler';
|
||||||
import { useSyncRecentViewsWithRouter } from '../../../hooks/use-recent-views';
|
import { useSyncRecentViewsWithRouter } from '../../../hooks/use-recent-views';
|
||||||
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 { WorkspaceAdapters } from '../../../plugins';
|
import { WorkspaceAdapters } from '../../../plugins';
|
||||||
@@ -110,7 +109,6 @@ const WorkspaceDetailPage: NextPageWithLayout = () => {
|
|||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const currentWorkspace = useAtomValue(rootCurrentWorkspaceAtom);
|
const currentWorkspace = useAtomValue(rootCurrentWorkspaceAtom);
|
||||||
const currentPageId = useAtomValue(rootCurrentPageIdAtom);
|
const currentPageId = useAtomValue(rootCurrentPageIdAtom);
|
||||||
useRouterAndWorkspaceWithPageIdDefense(router);
|
|
||||||
const page = useBlockSuiteWorkspacePage(
|
const page = useBlockSuiteWorkspacePage(
|
||||||
currentWorkspace.blockSuiteWorkspace,
|
currentWorkspace.blockSuiteWorkspace,
|
||||||
currentPageId
|
currentPageId
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import { PageLoading } from '../../../components/pure/loading';
|
|||||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
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 { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||||
import { WorkspaceAdapters } from '../../../plugins';
|
import { WorkspaceAdapters } from '../../../plugins';
|
||||||
import type { NextPageWithLayout } from '../../../shared';
|
import type { NextPageWithLayout } from '../../../shared';
|
||||||
@@ -24,7 +23,6 @@ const AllPage: NextPageWithLayout = () => {
|
|||||||
const { jumpToPage } = useRouterHelper(router);
|
const { jumpToPage } = useRouterHelper(router);
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
const onClickPage = useCallback(
|
const onClickPage = useCallback(
|
||||||
(pageId: string, newTab?: boolean) => {
|
(pageId: string, newTab?: boolean) => {
|
||||||
assertExists(currentWorkspace);
|
assertExists(currentWorkspace);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { PageLoading } from '../../../components/pure/loading';
|
|||||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
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 { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||||
import type { NextPageWithLayout } from '../../../shared';
|
import type { NextPageWithLayout } from '../../../shared';
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ const FavouritePage: NextPageWithLayout = () => {
|
|||||||
const { jumpToPage } = useRouterHelper(router);
|
const { jumpToPage } = useRouterHelper(router);
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
const onClickPage = useCallback(
|
const onClickPage = useCallback(
|
||||||
(pageId: string, newTab?: boolean) => {
|
(pageId: string, newTab?: boolean) => {
|
||||||
assertExists(currentWorkspace);
|
assertExists(currentWorkspace);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import { PageLoading } from '../../../components/pure/loading';
|
|||||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
import { useOnTransformWorkspace } from '../../../hooks/root/use-on-transform-workspace';
|
import { useOnTransformWorkspace } from '../../../hooks/root/use-on-transform-workspace';
|
||||||
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 { WorkspaceAdapters } from '../../../plugins';
|
import { WorkspaceAdapters } from '../../../plugins';
|
||||||
@@ -84,7 +83,6 @@ const SettingPage: NextPageWithLayout = () => {
|
|||||||
const workspaceIds = useAtomValue(rootWorkspacesMetadataAtom);
|
const workspaceIds = useAtomValue(rootWorkspacesMetadataAtom);
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
const [currentTab, setCurrentTab] = useAtom(settingPanelAtom);
|
const [currentTab, setCurrentTab] = useAtom(settingPanelAtom);
|
||||||
useEffect(() => {});
|
useEffect(() => {});
|
||||||
const onChangeTab = useCallback(
|
const onChangeTab = useCallback(
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { PageLoading } from '../../../components/pure/loading';
|
|||||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
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 { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||||
import type { NextPageWithLayout } from '../../../shared';
|
import type { NextPageWithLayout } from '../../../shared';
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ const SharedPages: NextPageWithLayout = () => {
|
|||||||
const { jumpToPage } = useRouterHelper(router);
|
const { jumpToPage } = useRouterHelper(router);
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
const onClickPage = useCallback(
|
const onClickPage = useCallback(
|
||||||
(pageId: string, newTab?: boolean) => {
|
(pageId: string, newTab?: boolean) => {
|
||||||
assertExists(currentWorkspace);
|
assertExists(currentWorkspace);
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import { PageLoading } from '../../../components/pure/loading';
|
|||||||
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
import { WorkspaceTitle } from '../../../components/pure/workspace-title';
|
||||||
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
import { useCurrentWorkspace } from '../../../hooks/current/use-current-workspace';
|
||||||
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 { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
import { WorkspaceLayout } from '../../../layouts/workspace-layout';
|
||||||
import type { NextPageWithLayout } from '../../../shared';
|
import type { NextPageWithLayout } from '../../../shared';
|
||||||
|
|
||||||
@@ -19,7 +18,6 @@ const TrashPage: NextPageWithLayout = () => {
|
|||||||
const { jumpToPage } = useRouterHelper(router);
|
const { jumpToPage } = useRouterHelper(router);
|
||||||
const [currentWorkspace] = useCurrentWorkspace();
|
const [currentWorkspace] = useCurrentWorkspace();
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
useSyncRouterWithCurrentWorkspaceId(router);
|
|
||||||
const onClickPage = useCallback(
|
const onClickPage = useCallback(
|
||||||
(pageId: string, newTab?: boolean) => {
|
(pageId: string, newTab?: boolean) => {
|
||||||
assertExists(currentWorkspace);
|
assertExists(currentWorkspace);
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ export function Modals() {
|
|||||||
setOpenCreateWorkspaceModal(false);
|
setOpenCreateWorkspaceModal(false);
|
||||||
setOpenWorkspacesModal(false);
|
setOpenWorkspacesModal(false);
|
||||||
setCurrentWorkspace(id);
|
setCurrentWorkspace(id);
|
||||||
return jumpToSubPath(id, WorkspaceSubPath.SETTING);
|
return jumpToSubPath(id, WorkspaceSubPath.ALL);
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
jumpToSubPath,
|
jumpToSubPath,
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/ws": "^8.5.4",
|
"@types/ws": "^8.5.4",
|
||||||
|
"next": "^13.4.1",
|
||||||
"ws": "^8.13.0"
|
"ws": "^8.13.0"
|
||||||
},
|
},
|
||||||
"version": "0.6.0-canary.0"
|
"version": "0.6.0-canary.0"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { EditorContainer } from '@blocksuite/editor';
|
import type { EditorContainer } from '@blocksuite/editor';
|
||||||
import { atom, createStore } from 'jotai';
|
import { atom, createStore } from 'jotai';
|
||||||
import { atomWithStorage, createJSONStorage } from 'jotai/utils';
|
import { atomWithStorage, createJSONStorage } from 'jotai/utils';
|
||||||
|
import Router from 'next/router';
|
||||||
|
|
||||||
import type { WorkspaceFlavour } from './type';
|
import type { WorkspaceFlavour } from './type';
|
||||||
|
|
||||||
@@ -32,12 +33,49 @@ export const rootCurrentWorkspaceIdAtom = atomWithStorage<string | null>(
|
|||||||
null,
|
null,
|
||||||
createJSONStorage(() => sessionStorage)
|
createJSONStorage(() => sessionStorage)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rootCurrentWorkspaceIdAtom.onMount = set => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const callback = (url: string) => {
|
||||||
|
const value = url.split('/')[2];
|
||||||
|
if (value) {
|
||||||
|
set(value);
|
||||||
|
} else {
|
||||||
|
set(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
callback(window.location.pathname);
|
||||||
|
Router.events.on('routeChangeStart', callback);
|
||||||
|
return () => {
|
||||||
|
Router.events.off('routeChangeStart', callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
export const rootCurrentPageIdAtom = atomWithStorage<string | null>(
|
export const rootCurrentPageIdAtom = atomWithStorage<string | null>(
|
||||||
'root-current-page-id',
|
'root-current-page-id',
|
||||||
null,
|
null,
|
||||||
createJSONStorage(() => sessionStorage)
|
createJSONStorage(() => sessionStorage)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
rootCurrentPageIdAtom.onMount = set => {
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
const callback = (url: string) => {
|
||||||
|
const value = url.split('/')[3];
|
||||||
|
if (value) {
|
||||||
|
set(value);
|
||||||
|
} else {
|
||||||
|
set(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
callback(window.location.pathname);
|
||||||
|
Router.events.on('routeChangeStart', callback);
|
||||||
|
return () => {
|
||||||
|
Router.events.off('routeChangeStart', callback);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// current editor atom, each app should have only one editor in the same time
|
// current editor atom, each app should have only one editor in the same time
|
||||||
export const rootCurrentEditorAtom = atom<Readonly<EditorContainer> | null>(
|
export const rootCurrentEditorAtom = atom<Readonly<EditorContainer> | null>(
|
||||||
null
|
null
|
||||||
|
|||||||
@@ -36,9 +36,6 @@ test('public single page', async ({ page, browser }) => {
|
|||||||
);
|
);
|
||||||
await page.getByTestId('confirm-enable-cloud-button').click();
|
await page.getByTestId('confirm-enable-cloud-button').click();
|
||||||
await promise;
|
await promise;
|
||||||
const newPage2Url = page.url().split('/');
|
|
||||||
newPage2Url[newPage2Url.length - 1] = page2Id as string;
|
|
||||||
await page.goto(newPage2Url.join('/'));
|
|
||||||
await page.waitForSelector('v-line');
|
await page.waitForSelector('v-line');
|
||||||
const currentTitle = await page
|
const currentTitle = await page
|
||||||
.locator('[data-block-is-title="true"]')
|
.locator('[data-block-is-title="true"]')
|
||||||
|
|||||||
@@ -46,9 +46,10 @@ test('should enable affine workspace successfully', async ({ page }) => {
|
|||||||
await page.locator('[data-block-is-title="true"]').type('Hello, world!', {
|
await page.locator('[data-block-is-title="true"]').type('Hello, world!', {
|
||||||
delay: 50,
|
delay: 50,
|
||||||
});
|
});
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
await assertCurrentWorkspaceFlavour('affine', page);
|
await assertCurrentWorkspaceFlavour('affine', page);
|
||||||
await openWorkspaceListModal(page);
|
await openWorkspaceListModal(page);
|
||||||
await page.getByTestId('workspace-list-modal-sign-out').click();
|
await page.getByTestId('workspace-list-modal-sign-out').click();
|
||||||
await page.waitForTimeout(1000);
|
await waitMarkdownImported(page);
|
||||||
await assertCurrentWorkspaceFlavour('local', page);
|
await assertCurrentWorkspaceFlavour('local', page);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,9 +9,7 @@ test('Open last workspace when back to affine', async ({ page }) => {
|
|||||||
await openHomePage(page);
|
await openHomePage(page);
|
||||||
await waitMarkdownImported(page);
|
await waitMarkdownImported(page);
|
||||||
await createWorkspace({ name: 'New Workspace 2' }, page);
|
await createWorkspace({ name: 'New Workspace 2' }, page);
|
||||||
// FIXME: can not get when the new workspace is surely created, hack a timeout to wait
|
await waitMarkdownImported(page);
|
||||||
// waiting for page loading end
|
|
||||||
await page.waitForTimeout(3000);
|
|
||||||
// show workspace list
|
// show workspace list
|
||||||
await page.getByTestId('workspace-name').click();
|
await page.getByTestId('workspace-name').click();
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { expect } from '@playwright/test';
|
|||||||
|
|
||||||
import { openHomePage, webUrl } from '../libs/load-page';
|
import { openHomePage, webUrl } from '../libs/load-page';
|
||||||
import { waitMarkdownImported } from '../libs/page-logic';
|
import { waitMarkdownImported } from '../libs/page-logic';
|
||||||
import { clickSideBarAllPageButton } from '../libs/sidebar';
|
|
||||||
|
|
||||||
test('goto not found page', async ({ page }) => {
|
test('goto not found page', async ({ page }) => {
|
||||||
await openHomePage(page);
|
await openHomePage(page);
|
||||||
@@ -17,9 +16,8 @@ test('goto not found page', async ({ page }) => {
|
|||||||
test('goto not found workspace', async ({ page }) => {
|
test('goto not found workspace', async ({ page }) => {
|
||||||
await openHomePage(page);
|
await openHomePage(page);
|
||||||
await waitMarkdownImported(page);
|
await waitMarkdownImported(page);
|
||||||
await clickSideBarAllPageButton(page);
|
|
||||||
const currentUrl = page.url();
|
const currentUrl = page.url();
|
||||||
await page.goto(new URL('/workspace/invalid/all', webUrl).toString());
|
await page.goto(new URL('/workspace/invalid/all', webUrl).toString());
|
||||||
await clickSideBarAllPageButton(page);
|
await page.waitForSelector('v-line');
|
||||||
expect(page.url()).toEqual(currentUrl);
|
expect(page.url()).toEqual(currentUrl);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user