Skip to content

Commit

Permalink
Merge branch 'canary' into ayush/bumpBS22022024
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn authored Feb 22, 2024
2 parents ea2c0fb + 35842ae commit 66ee886
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 96 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @vitest-environment happy-dom
*/
import 'fake-indexeddb/auto';

import { configureTestingEnvironment } from '@affine/core/testing';
import { renderHook } from '@testing-library/react';
import type { Workspace } from '@toeverything/infra';
import { initEmptyPage, ServiceProviderContext } from '@toeverything/infra';
import type { PropsWithChildren } from 'react';
import { beforeEach, describe, expect, test, vi } from 'vitest';

import { useBlockSuitePageMeta } from '../use-block-suite-page-meta';
import { useBlockSuiteWorkspaceHelper } from '../use-block-suite-workspace-helper';

const configureTestingWorkspace = async () => {
const { workspace } = await configureTestingEnvironment();
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;

// await initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page-0' }));
initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page1' }));
initEmptyPage(blockSuiteWorkspace.createPage({ id: 'page2' }));

return workspace;
};

beforeEach(async () => {
vi.useFakeTimers({ toFake: ['requestIdleCallback'] });
});

const getWrapper = (workspace: Workspace) =>
function Provider({ children }: PropsWithChildren) {
return (
<ServiceProviderContext.Provider value={workspace.services}>
{children}
</ServiceProviderContext.Provider>
);
};

describe('useBlockSuiteWorkspaceHelper', () => {
test('should create page', async () => {
const workspace = await configureTestingWorkspace();
const blockSuiteWorkspace = workspace.blockSuiteWorkspace;
const Wrapper = getWrapper(workspace);

expect(blockSuiteWorkspace.meta.pageMetas.length).toBe(3);
const helperHook = renderHook(
() => useBlockSuiteWorkspaceHelper(blockSuiteWorkspace),
{
wrapper: Wrapper,
}
);
const pageMetaHook = renderHook(
() => useBlockSuitePageMeta(blockSuiteWorkspace),
{
wrapper: Wrapper,
}
);
await new Promise(resolve => setTimeout(resolve));
expect(pageMetaHook.result.current.length).toBe(3);
expect(blockSuiteWorkspace.meta.pageMetas.length).toBe(3);
const page = helperHook.result.current.createPage('page4');
expect(page.id).toBe('page4');
expect(blockSuiteWorkspace.meta.pageMetas.length).toBe(4);
pageMetaHook.rerender();
expect(pageMetaHook.result.current.length).toBe(4);
});
});
4 changes: 2 additions & 2 deletions packages/frontend/core/src/hooks/use-affine-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { use } from 'foxact/use';
import { useEffect, useMemo, useState } from 'react';

import { WorkspacePropertiesAdapter } from '../modules/workspace/properties';
import { useBlockSuitePageMeta } from './use-block-suite-page-meta';
import { useAllBlockSuitePageMeta } from './use-all-block-suite-page-meta';

function getProxy<T extends object>(obj: T) {
return new Proxy(obj, {});
Expand All @@ -14,7 +14,7 @@ const useReactiveAdapter = (adapter: WorkspacePropertiesAdapter) => {
use(adapter.workspace.blockSuiteWorkspace.doc.whenSynced);
const [proxy, setProxy] = useState(adapter);
// fixme: this is a hack to force re-render when default meta changed
useBlockSuitePageMeta(adapter.workspace.blockSuiteWorkspace);
useAllBlockSuitePageMeta(adapter.workspace.blockSuiteWorkspace);
useEffect(() => {
// todo: track which properties are used and then filter by property path change
// using Y.YEvent.path
Expand Down
25 changes: 25 additions & 0 deletions packages/frontend/core/src/hooks/use-all-block-suite-page-meta.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import type { PageMeta, Workspace } from '@blocksuite/store';
import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai';

const weakMap = new WeakMap<Workspace, Atom<PageMeta[]>>();

// this hook is extracted from './use-block-suite-page-meta.ts' to avoid circular dependency
export function useAllBlockSuitePageMeta(
blockSuiteWorkspace: Workspace
): PageMeta[] {
if (!weakMap.has(blockSuiteWorkspace)) {
const baseAtom = atom<PageMeta[]>(blockSuiteWorkspace.meta.pageMetas);
weakMap.set(blockSuiteWorkspace, baseAtom);
baseAtom.onMount = set => {
set(blockSuiteWorkspace.meta.pageMetas);
const dispose = blockSuiteWorkspace.meta.pageMetasUpdated.on(() => {
set(blockSuiteWorkspace.meta.pageMetas);
});
return () => {
dispose.dispose();
};
};
}
return useAtomValue(weakMap.get(blockSuiteWorkspace) as Atom<PageMeta[]>);
}
37 changes: 17 additions & 20 deletions packages/frontend/core/src/hooks/use-block-suite-page-meta.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,26 @@
import type { PageBlockModel } from '@blocksuite/blocks';
import { assertExists } from '@blocksuite/global/utils';
import type { PageMeta, Workspace } from '@blocksuite/store';
import type { Atom } from 'jotai';
import { atom, useAtomValue } from 'jotai';
import { useMemo } from 'react';

const weakMap = new WeakMap<Workspace, Atom<PageMeta[]>>();
import { useAllBlockSuitePageMeta } from './use-all-block-suite-page-meta';
import { useJournalHelper } from './use-journal';

export function useBlockSuitePageMeta(
blockSuiteWorkspace: Workspace
): PageMeta[] {
if (!weakMap.has(blockSuiteWorkspace)) {
const baseAtom = atom<PageMeta[]>(blockSuiteWorkspace.meta.pageMetas);
weakMap.set(blockSuiteWorkspace, baseAtom);
baseAtom.onMount = set => {
set(blockSuiteWorkspace.meta.pageMetas);
const dispose = blockSuiteWorkspace.meta.pageMetasUpdated.on(() => {
set(blockSuiteWorkspace.meta.pageMetas);
});
return () => {
dispose.dispose();
};
};
}
return useAtomValue(weakMap.get(blockSuiteWorkspace) as Atom<PageMeta[]>);
/**
* Get pageMetas excluding journal pages without updatedDate
* If you want to get all pageMetas, use `useAllBlockSuitePageMeta` instead
* @returns
*/
export function useBlockSuitePageMeta(blocksuiteWorkspace: Workspace) {
const pageMetas = useAllBlockSuitePageMeta(blocksuiteWorkspace);
const { isPageJournal } = useJournalHelper(blocksuiteWorkspace);
return useMemo(
() =>
pageMetas.filter(
pageMeta => !isPageJournal(pageMeta.id) || !!pageMeta.updatedDate
),
[isPageJournal, pageMetas]
);
}

export function usePageMetaHelper(blockSuiteWorkspace: Workspace) {
Expand Down
7 changes: 5 additions & 2 deletions packages/frontend/core/src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@ export const Component = () => {
const [creating, setCreating] = useState(false);

const list = useLiveData(useService(WorkspaceListService).workspaceList);
const workspaceStatus = useLiveData(useService(WorkspaceListService).status);

const { openPage } = useNavigateHelper();

useLayoutEffect(() => {
if (list.length === 0) {
if (list.length === 0 || workspaceStatus.loading) {
return;
}

// open last workspace
const lastId = localStorage.getItem('last_workspace_id');

const openWorkspace = list.find(w => w.id === lastId) ?? list[0];
openPage(openWorkspace.id, WorkspaceSubPath.ALL);
setNavigating(true);
}, [list, openPage]);
}, [list, workspaceStatus, openPage]);

const workspaceManager = useService(WorkspaceManager);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,23 @@ import {
} from '@affine/component';
import { MoveToTrash } from '@affine/core/components/page-list';
import { useTrashModalHelper } from '@affine/core/hooks/affine/use-trash-modal-helper';
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
import { useBlockSuiteWorkspacePageTitle } from '@affine/core/hooks/use-block-suite-workspace-page-title';
import {
useJournalHelper,
useJournalInfoHelper,
useJournalRouteHelper,
} from '@affine/core/hooks/use-journal';
import { useNavigateHelper } from '@affine/core/hooks/use-navigate-helper';
import type { BlockSuiteWorkspace } from '@affine/core/shared';
import { useAFFiNEI18N } from '@affine/i18n/hooks';
import {
EdgelessIcon,
MoreHorizontalIcon,
PageIcon,
TodayIcon,
} from '@blocksuite/icons';
import type { Page } from '@blocksuite/store';
import type { Page, PageMeta } from '@blocksuite/store';
import { assignInlineVars } from '@vanilla-extract/dynamic';
import clsx from 'clsx';
import dayjs from 'dayjs';
Expand All @@ -42,21 +44,28 @@ const CountDisplay = ({
return <span {...attrs}>{count > max ? `${max}+` : count}</span>;
};
interface PageItemProps extends HTMLAttributes<HTMLDivElement> {
page: Page;
pageMeta: PageMeta;
workspace: BlockSuiteWorkspace;
right?: ReactNode;
}
const PageItem = ({ page, right, className, ...attrs }: PageItemProps) => {
const { isJournal } = useJournalInfoHelper(page.workspace, page.id);
const title = useBlockSuiteWorkspacePageTitle(page.workspace, page.id);
const PageItem = ({
pageMeta,
workspace,
right,
className,
...attrs
}: PageItemProps) => {
const { isJournal } = useJournalInfoHelper(workspace, pageMeta.id);
const title = useBlockSuiteWorkspacePageTitle(workspace, pageMeta.id);

const Icon = isJournal
? TodayIcon
: page.meta.mode === 'edgeless'
: pageMeta.mode === 'edgeless'
? EdgelessIcon
: PageIcon;
return (
<div
aria-label={page.meta.title}
aria-label={pageMeta.title}
className={clsx(className, styles.pageItem)}
{...attrs}
>
Expand Down Expand Up @@ -147,15 +156,12 @@ const EditorJournalPanel = (props: EditorExtensionProps) => {
};

const sortPagesByDate = (
pages: Page[],
pages: PageMeta[],
field: 'updatedDate' | 'createDate',
order: 'asc' | 'desc' = 'desc'
) => {
return [...pages].sort((a, b) => {
return (
(order === 'asc' ? 1 : -1) *
dayjs(b.meta[field]).diff(dayjs(a.meta[field]))
);
return (order === 'asc' ? 1 : -1) * dayjs(b[field]).diff(dayjs(a[field]));
});
};

Expand All @@ -174,21 +180,21 @@ const JournalDailyCountBlock = ({ workspace, date }: JournalBlockProps) => {
const nodeRef = useRef<HTMLDivElement>(null);
const t = useAFFiNEI18N();
const [activeItem, setActiveItem] = useState<NavItemName>('createdToday');
const pageMetas = useBlockSuitePageMeta(workspace);

const navigateHelper = useNavigateHelper();

const getTodaysPages = useCallback(
(field: 'createDate' | 'updatedDate') => {
const pages: Page[] = [];
Array.from(workspace.pages.values()).forEach(page => {
if (page.meta.trash) return;
if (page.meta[field] && dayjs(page.meta[field]).isSame(date, 'day')) {
pages.push(page);
}
});
return sortPagesByDate(pages, field);
return sortPagesByDate(
pageMetas.filter(pageMeta => {
if (pageMeta.trash) return false;
return pageMeta[field] && dayjs(pageMeta[field]).isSame(date, 'day');
}),
field
);
},
[date, workspace.pages]
[date, pageMetas]
);

const createdToday = useMemo(
Expand Down Expand Up @@ -257,14 +263,15 @@ const JournalDailyCountBlock = ({ workspace, date }: JournalBlockProps) => {
<Scrollable.Scrollbar />
<Scrollable.Viewport>
<div className={styles.dailyCountContent} ref={nodeRef}>
{renderList.map((page, index) => (
{renderList.map((pageMeta, index) => (
<PageItem
onClick={() =>
navigateHelper.openPage(workspace.id, page.id)
navigateHelper.openPage(workspace.id, pageMeta.id)
}
tabIndex={name === activeItem ? 0 : -1}
key={index}
page={page}
pageMeta={pageMeta}
workspace={workspace}
/>
))}
</div>
Expand Down Expand Up @@ -315,7 +322,8 @@ const ConflictList = ({
<PageItem
aria-label={page.meta.title}
aria-selected={isCurrent}
page={page}
pageMeta={page.meta}
workspace={workspace}
key={page.id}
right={
<Menu
Expand Down

0 comments on commit 66ee886

Please sign in to comment.