mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-14 13:25:12 +00:00
feat(core): page info adapter for journal (#5561)
Page info adapter + schema. Adapted for journal features. 
This commit is contained in:
39
packages/frontend/core/src/hooks/use-affine-adapter.ts
Normal file
39
packages/frontend/core/src/hooks/use-affine-adapter.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useEffect, useMemo, useReducer } from 'react';
|
||||
|
||||
import {
|
||||
currentWorkspacePropertiesAdapterAtom,
|
||||
WorkspacePropertiesAdapter,
|
||||
} from '../modules/workspace';
|
||||
|
||||
const useReactiveAdapter = (adapter: WorkspacePropertiesAdapter) => {
|
||||
const [, forceUpdate] = useReducer(c => c + 1, 0);
|
||||
|
||||
useEffect(() => {
|
||||
// todo: track which properties are used and then filter by property path change
|
||||
// using Y.YEvent.path
|
||||
function observe() {
|
||||
forceUpdate();
|
||||
}
|
||||
adapter.properties.observeDeep(observe);
|
||||
return () => {
|
||||
adapter.properties.unobserveDeep(observe);
|
||||
};
|
||||
}, [adapter]);
|
||||
|
||||
return adapter;
|
||||
};
|
||||
|
||||
export function useCurrentWorkspacePropertiesAdapter() {
|
||||
const adapter = useAtomValue(currentWorkspacePropertiesAdapterAtom);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
|
||||
export function useWorkspacePropertiesAdapter(workspace: Workspace) {
|
||||
const adapter = useMemo(
|
||||
() => new WorkspacePropertiesAdapter(workspace),
|
||||
[workspace]
|
||||
);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { useBlockSuitePageMeta } from '@affine/core/hooks/use-block-suite-page-meta';
|
||||
import type { GetPageInfoById } from '@affine/env/page-info';
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import { pageSettingsAtom } from '../atoms';
|
||||
|
||||
export const useGetPageInfoById = (workspace: Workspace): GetPageInfoById => {
|
||||
const pageMetas = useBlockSuitePageMeta(workspace);
|
||||
const pageMap = useMemo(
|
||||
() => Object.fromEntries(pageMetas.map(page => [page.id, page])),
|
||||
[pageMetas]
|
||||
);
|
||||
const pageSettings = useAtomValue(pageSettingsAtom);
|
||||
return useCallback(
|
||||
(id: string) => {
|
||||
const page = pageMap[id];
|
||||
if (!page) {
|
||||
return;
|
||||
}
|
||||
return {
|
||||
...page,
|
||||
isEdgeless: pageSettings[id]?.mode === 'edgeless',
|
||||
};
|
||||
},
|
||||
[pageMap, pageSettings]
|
||||
);
|
||||
};
|
||||
@@ -1,31 +1,34 @@
|
||||
import type { PageMeta } from '@blocksuite/store';
|
||||
import { initEmptyPage } from '@toeverything/infra/blocksuite';
|
||||
import dayjs from 'dayjs';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
import type { BlockSuiteWorkspace } from '../shared';
|
||||
import { timestampToLocalDate } from '../utils';
|
||||
import { useWorkspacePropertiesAdapter } from './use-affine-adapter';
|
||||
import { useBlockSuiteWorkspaceHelper } from './use-block-suite-workspace-helper';
|
||||
import { useNavigateHelper } from './use-navigate-helper';
|
||||
|
||||
type MaybeDate = Date | string | number;
|
||||
export const JOURNAL_DATE_FORMAT = 'YYYY-MM-DD';
|
||||
|
||||
function isPageJournal(pageMeta?: PageMeta) {
|
||||
function isJournalString(j?: string | false) {
|
||||
if (!runtimeConfig.enableJournal) return false;
|
||||
return !!(pageMeta && pageMeta.title.match(/^\d{4}-\d{2}-\d{2}$/));
|
||||
return j ? !!j?.match(/^\d{4}-\d{2}-\d{2}$/) : false;
|
||||
}
|
||||
|
||||
function getJournalDate(pageMeta?: PageMeta) {
|
||||
if (!isPageJournal(pageMeta)) return null;
|
||||
if (!pageMeta?.title) return null;
|
||||
if (!dayjs(pageMeta.title).isValid()) return null;
|
||||
return dayjs(pageMeta.title);
|
||||
function toDayjs(j?: string | false) {
|
||||
if (!j || !isJournalString(j)) return null;
|
||||
const day = dayjs(j);
|
||||
if (!day.isValid()) return null;
|
||||
return day;
|
||||
}
|
||||
|
||||
export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
|
||||
const bsWorkspaceHelper = useBlockSuiteWorkspaceHelper(workspace);
|
||||
const navigateHelper = useNavigateHelper();
|
||||
|
||||
const adapter = useWorkspacePropertiesAdapter(workspace);
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
@@ -36,9 +39,17 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
|
||||
initEmptyPage(page, title).catch(err =>
|
||||
console.error('Failed to load journal page', err)
|
||||
);
|
||||
adapter.setJournalPageDateString(page.id, title);
|
||||
return page;
|
||||
},
|
||||
[bsWorkspaceHelper]
|
||||
[adapter, bsWorkspaceHelper]
|
||||
);
|
||||
|
||||
const isPageJournal = useCallback(
|
||||
(pageId: string) => {
|
||||
return !!adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -48,14 +59,15 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
|
||||
(maybeDate: MaybeDate) => {
|
||||
const day = dayjs(maybeDate);
|
||||
return Array.from(workspace.pages.values()).filter(page => {
|
||||
if (!isPageJournal(page.meta)) return false;
|
||||
const pageId = page.id;
|
||||
if (!isPageJournal(pageId)) return false;
|
||||
if (page.meta.trash) return false;
|
||||
const journalDate = getJournalDate(page.meta);
|
||||
const journalDate = adapter.getJournalPageDateString(page.id);
|
||||
if (!journalDate) return false;
|
||||
return day.isSame(journalDate, 'day');
|
||||
});
|
||||
},
|
||||
[workspace.pages]
|
||||
[adapter, isPageJournal, workspace.pages]
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -89,26 +101,59 @@ export const useJournalHelper = (workspace: BlockSuiteWorkspace) => {
|
||||
openJournal(date);
|
||||
}, [openJournal]);
|
||||
|
||||
const getJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
return adapter.getJournalPageDateString(pageId);
|
||||
},
|
||||
[adapter]
|
||||
);
|
||||
|
||||
const getLocalizedJournalDateString = useCallback(
|
||||
(pageId: string) => {
|
||||
const journalDateString = getJournalDateString(pageId);
|
||||
if (!journalDateString) return null;
|
||||
return timestampToLocalDate(journalDateString);
|
||||
},
|
||||
[getJournalDateString]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
getJournalsByDate,
|
||||
getJournalByDate,
|
||||
getJournalDateString,
|
||||
getLocalizedJournalDateString,
|
||||
openJournal,
|
||||
openToday,
|
||||
isPageJournal,
|
||||
}),
|
||||
[getJournalByDate, getJournalsByDate, openJournal, openToday]
|
||||
[
|
||||
getJournalByDate,
|
||||
getJournalDateString,
|
||||
getJournalsByDate,
|
||||
getLocalizedJournalDateString,
|
||||
isPageJournal,
|
||||
openJournal,
|
||||
openToday,
|
||||
]
|
||||
);
|
||||
};
|
||||
|
||||
export const useJournalInfoHelper = (pageMeta?: PageMeta) => {
|
||||
const isJournal = isPageJournal(pageMeta);
|
||||
const journalDate = useMemo(() => getJournalDate(pageMeta), [pageMeta]);
|
||||
export const useJournalInfoHelper = (
|
||||
workspace: BlockSuiteWorkspace,
|
||||
pageId?: string | null
|
||||
) => {
|
||||
const { isPageJournal, getJournalDateString } = useJournalHelper(workspace);
|
||||
const journalDate = useMemo(
|
||||
() => (pageId ? toDayjs(getJournalDateString(pageId)) : null),
|
||||
[getJournalDateString, pageId]
|
||||
);
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
isJournal,
|
||||
isJournal: pageId ? isPageJournal(pageId) : false,
|
||||
journalDate,
|
||||
}),
|
||||
[isJournal, journalDate]
|
||||
[isPageJournal, journalDate, pageId]
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user