feat: add recentlyViewed (#1357)

Co-authored-by: himself65 <himself65@outlook.com>
This commit is contained in:
JimmFly
2023-03-07 02:02:50 +08:00
committed by GitHub
parent 2a08e0b704
commit 776d30613f
5 changed files with 195 additions and 23 deletions

View File

@@ -13,10 +13,23 @@ import { useRouter } from 'next/router';
import routerMock from 'next-router-mock';
import { createDynamicRouteParser } from 'next-router-mock/dynamic-routes';
import React from 'react';
import { beforeAll, beforeEach, describe, expect, test } from 'vitest';
import { beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
import { workspacesAtom } from '../../atoms';
import { BlockSuiteWorkspace, RemWorkspaceFlavour } from '../../shared';
import {
currentWorkspaceIdAtom,
jotaiWorkspacesAtom,
workspacesAtom,
} from '../../atoms';
import { LocalPlugin } from '../../plugins/local';
import {
BlockSuiteWorkspace,
LocalWorkspace,
RemWorkspaceFlavour,
} from '../../shared';
import {
useRecentlyViewed,
useSyncRecentViewsWithRouter,
} from '../affine/use-recent-views';
import {
currentWorkspaceAtom,
useCurrentWorkspace,
@@ -248,3 +261,59 @@ describe('useBlockSuiteWorkspaceName', () => {
expect(blockSuiteWorkspace.meta.name).toBe('test 3');
});
});
describe('useRecentlyViewed', () => {
test('basic', async () => {
const { ProviderWrapper, store } = await getJotaiContext();
const workspaceId = blockSuiteWorkspace.room as string;
const pageId = 'page0';
store.set(jotaiWorkspacesAtom, [
{
id: workspaceId,
flavour: RemWorkspaceFlavour.LOCAL,
},
]);
LocalPlugin.CRUD.get = vi.fn().mockResolvedValue({
id: workspaceId,
flavour: RemWorkspaceFlavour.LOCAL,
blockSuiteWorkspace,
providers: [],
} satisfies LocalWorkspace);
store.set(currentWorkspaceIdAtom, blockSuiteWorkspace.room as string);
const workspace = await store.get(currentWorkspaceAtom);
expect(workspace?.id).toBe(blockSuiteWorkspace.room as string);
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),
{
wrapper: ProviderWrapper,
initialProps: routerHook.result.current,
}
);
syncHook.rerender(routerHook.result.current);
expect(recentlyViewedHook.result.current).toEqual([
{
id: 'page0',
mode: 'page',
title: 'Untitled',
},
]);
});
});

View File

@@ -0,0 +1,40 @@
import { useAtomValue, useSetAtom } from 'jotai';
import { NextRouter } from 'next/router';
import { useEffect } from 'react';
import {
workspaceRecentViewsAtom,
workspaceRecentViresWriteAtom,
} from '../../atoms';
import { useCurrentWorkspace } from '../current/use-current-workspace';
import { usePageMeta } from '../use-page-meta';
export function useRecentlyViewed() {
const [workspace] = useCurrentWorkspace();
const workspaceId = workspace?.id || null;
const recentlyViewed = useAtomValue(workspaceRecentViewsAtom);
if (!workspaceId) return [];
return recentlyViewed[workspaceId] ?? [];
}
export function useSyncRecentViewsWithRouter(router: NextRouter) {
const [workspace] = useCurrentWorkspace();
const workspaceId = workspace?.id || null;
const blockSuiteWorkspace = workspace?.blockSuiteWorkspace || null;
const pageId = router.query.pageId as string;
const set = useSetAtom(workspaceRecentViresWriteAtom);
const meta = usePageMeta(blockSuiteWorkspace).find(
meta => meta.id === pageId
);
useEffect(() => {
if (!workspaceId) return;
if (pageId && meta) {
set(workspaceId, {
title: meta.title || 'Untitled',
id: pageId as string,
mode: meta.mode || 'page',
});
}
}, [pageId, meta, workspaceId, set]);
}