mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-19 02:56:23 +08:00
feat(core): page info ui (#5729)
this PR includes the main table view in the page detail page
This commit is contained in:
@@ -1,20 +1,27 @@
|
||||
import type { Workspace } from '@toeverything/infra';
|
||||
import { useService } from '@toeverything/infra/di';
|
||||
import { useEffect, useState } from 'react';
|
||||
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';
|
||||
|
||||
function getProxy<T extends object>(obj: T) {
|
||||
return new Proxy(obj, {});
|
||||
}
|
||||
|
||||
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);
|
||||
useEffect(() => {
|
||||
// todo: track which properties are used and then filter by property path change
|
||||
// using Y.YEvent.path
|
||||
function observe() {
|
||||
setProxy(getProxy(adapter));
|
||||
requestAnimationFrame(() => {
|
||||
setProxy(getProxy(adapter));
|
||||
});
|
||||
}
|
||||
adapter.properties.observeDeep(observe);
|
||||
return () => {
|
||||
@@ -29,3 +36,11 @@ export function useCurrentWorkspacePropertiesAdapter() {
|
||||
const adapter = useService(WorkspacePropertiesAdapter);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
|
||||
export function useWorkspacePropertiesAdapter(workspace: Workspace) {
|
||||
const adapter = useMemo(
|
||||
() => new WorkspacePropertiesAdapter(workspace),
|
||||
[workspace]
|
||||
);
|
||||
return useReactiveAdapter(adapter);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { Page, Workspace } from '@blocksuite/store';
|
||||
import { type Atom, atom, useAtomValue } from 'jotai';
|
||||
|
||||
import { useBlockSuiteWorkspacePage } from './use-block-suite-workspace-page';
|
||||
|
||||
const weakMap = new WeakMap<Page, Atom<string[]>>();
|
||||
function getPageBacklinks(page: Page): string[] {
|
||||
return page.workspace.indexer.backlink
|
||||
.getBacklink(page.id)
|
||||
.map(linkNode => linkNode.pageId)
|
||||
.filter(id => id !== page.id);
|
||||
}
|
||||
|
||||
const getPageBacklinksAtom = (page: Page | null) => {
|
||||
if (!page) {
|
||||
return atom([]);
|
||||
}
|
||||
|
||||
if (!weakMap.has(page)) {
|
||||
const baseAtom = atom<string[]>([]);
|
||||
baseAtom.onMount = set => {
|
||||
const disposables = [
|
||||
page.slots.ready.on(() => {
|
||||
set(getPageBacklinks(page));
|
||||
}),
|
||||
page.workspace.indexer.backlink.slots.indexUpdated.on(() => {
|
||||
set(getPageBacklinks(page));
|
||||
}),
|
||||
];
|
||||
set(getPageBacklinks(page));
|
||||
return () => {
|
||||
disposables.forEach(disposable => disposable.dispose());
|
||||
};
|
||||
};
|
||||
weakMap.set(page, baseAtom);
|
||||
}
|
||||
return weakMap.get(page) as Atom<string[]>;
|
||||
};
|
||||
|
||||
export function useBlockSuitePageBacklinks(
|
||||
blockSuiteWorkspace: Workspace,
|
||||
pageId: string
|
||||
): string[] {
|
||||
const page = useBlockSuiteWorkspacePage(blockSuiteWorkspace, pageId);
|
||||
return useAtomValue(getPageBacklinksAtom(page));
|
||||
}
|
||||
@@ -25,9 +25,11 @@ export function useWorkspaceStatus<
|
||||
setStatus(
|
||||
cachedSelector ? cachedSelector(workspace.status) : workspace.status
|
||||
);
|
||||
return workspace.onStatusChange.on(status =>
|
||||
setStatus(cachedSelector ? cachedSelector(status) : status)
|
||||
).dispose;
|
||||
return workspace.onStatusChange.on(status => {
|
||||
requestAnimationFrame(() => {
|
||||
setStatus(cachedSelector ? cachedSelector(status) : status);
|
||||
});
|
||||
}).dispose;
|
||||
}, [cachedSelector, workspace]);
|
||||
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user