feat: connect pinboard and reference link (#1859)

This commit is contained in:
Qi
2023-04-11 00:49:51 +08:00
committed by GitHub
parent 9acbba7016
commit ea2a146c82
12 changed files with 243 additions and 91 deletions
@@ -0,0 +1,42 @@
import { useAtomValue } from 'jotai';
import { useEffect } from 'react';
import { currentEditorAtom } from '../../atoms';
export function useReferenceLink(props?: {
pageLinkClicked?: (params: { pageId: string }) => void;
subpageLinked?: (params: { pageId: string }) => void;
subpageUnlinked?: (params: { pageId: string }) => void;
}) {
const { pageLinkClicked, subpageLinked, subpageUnlinked } = props ?? {};
const editor = useAtomValue(currentEditorAtom);
useEffect(() => {
if (!editor) {
return;
}
const linkClickedDisposable = editor.slots.pageLinkClicked.on(
({ pageId }) => {
pageLinkClicked?.({ pageId });
}
);
const subpageLinkedDisposable = editor.slots.subpageLinked.on(
({ pageId }) => {
subpageLinked?.({ pageId });
}
);
const subpageUnlinkedDisposable = editor.slots.subpageUnlinked.on(
({ pageId }) => {
subpageUnlinked?.({ pageId });
}
);
return () => {
linkClickedDisposable.dispose();
subpageLinkedDisposable.dispose();
subpageUnlinkedDisposable.dispose();
};
}, [editor, pageLinkClicked, subpageLinked, subpageUnlinked]);
}
+49 -20
View File
@@ -7,7 +7,7 @@ import { useCallback } from 'react';
import type { BlockSuiteWorkspace } from '../shared';
import { useBlockSuiteWorkspaceHelper } from './use-blocksuite-workspace-helper';
import { usePageMetaHelper } from './use-page-meta';
import type { NodeRenderProps, PinboardNode } from './use-pinboard-data';
import type { NodeRenderProps } from './use-pinboard-data';
const logger = new DebugLogger('pinboard');
@@ -25,7 +25,7 @@ export function usePinboardHandler({
onDelete,
onDrop,
}: {
blockSuiteWorkspace: BlockSuiteWorkspace;
blockSuiteWorkspace: BlockSuiteWorkspace | null;
metas: PageMeta[];
onAdd?: (addedId: string, parentId: string) => void;
onDelete?: TreeViewProps<NodeRenderProps>['onDelete'];
@@ -34,17 +34,43 @@ export function usePinboardHandler({
const { createPage } = useBlockSuiteWorkspaceHelper(blockSuiteWorkspace);
const { getPageMeta, setPageMeta } = usePageMetaHelper(blockSuiteWorkspace);
const handleAdd = useCallback(
(node: PinboardNode) => {
const id = nanoid();
createPage(id, node.id);
onAdd?.(id, node.id);
// Just need handle add operation, delete check is handled in blockSuite's reference link
const addReferenceLink = useCallback(
(pageId: string, referenceId: string) => {
const page = blockSuiteWorkspace?.getPage(pageId);
if (!page) {
return;
}
const text = page.Text.fromDelta([
{
insert: ' ',
attributes: {
reference: {
type: 'Subpage',
pageId: referenceId,
},
},
},
]);
const [frame] = page.getBlockByFlavour('affine:frame');
frame && page.addBlock('affine:paragraph', { text }, frame.id);
},
[createPage, onAdd]
[blockSuiteWorkspace]
);
const handleDelete = useCallback(
(node: PinboardNode) => {
const addPin = useCallback(
(parentId: string) => {
const id = nanoid();
createPage(id, parentId);
onAdd?.(id, parentId);
addReferenceLink(parentId, id);
},
[addReferenceLink, createPage, onAdd]
);
const deletePin = useCallback(
(deleteId: string) => {
const removeToTrash = (currentMeta: PageMeta) => {
const { subpageIds = [] } = currentMeta;
setPageMeta(currentMeta.id, {
@@ -52,17 +78,17 @@ export function usePinboardHandler({
trashDate: +new Date(),
});
subpageIds.forEach(id => {
const subcurrentMeta = getPageMeta(id);
subcurrentMeta && removeToTrash(subcurrentMeta);
const subCurrentMeta = getPageMeta(id);
subCurrentMeta && removeToTrash(subCurrentMeta);
});
};
removeToTrash(metas.find(m => m.id === node.id)!);
onDelete?.(node);
removeToTrash(metas.find(m => m.id === deleteId)!);
onDelete?.(deleteId);
},
[metas, getPageMeta, onDelete, setPageMeta]
);
const handleDrop = useCallback(
const dropPin = useCallback(
(
dragId: string,
dropId: string,
@@ -96,7 +122,7 @@ export function usePinboardHandler({
const dropParentMeta = metas.find(m => m.subpageIds?.includes(dropId));
if (dropParentMeta?.id === dragParentMeta?.id) {
// same parent
// same parent, resort node
const newSubpageIds = [...(dragParentMeta?.subpageIds ?? [])];
const deleteIndex = newSubpageIds.findIndex(id => id === dragId);
newSubpageIds.splice(deleteIndex, 1);
@@ -109,6 +135,7 @@ export function usePinboardHandler({
});
return onDrop?.(dragId, dropId, position);
}
// Old parent will delete drag node, new parent will be added
const newDragParentSubpageIds = [...(dragParentMeta?.subpageIds ?? [])];
const deleteIndex = newDragParentSubpageIds.findIndex(
id => id === dragId
@@ -127,6 +154,7 @@ export function usePinboardHandler({
setPageMeta(dropParentMeta.id, {
subpageIds: newDropParentSubpageIds,
});
dropParentMeta && addReferenceLink(dropParentMeta.id, dragId);
return onDrop?.(dragId, dropId, position);
}
@@ -149,14 +177,15 @@ export function usePinboardHandler({
setPageMeta(dropMeta.id, {
subpageIds: newSubpageIds,
});
addReferenceLink(dropMeta.id, dragId);
},
[metas, onDrop, setPageMeta]
[addReferenceLink, metas, onDrop, setPageMeta]
);
return {
handleDrop,
handleAdd,
handleDelete,
dropPin,
addPin,
deletePin,
};
}
+65 -42
View File
@@ -1,5 +1,5 @@
import type { NextRouter } from 'next/router';
import { useMemo } from 'react';
import { useCallback } from 'react';
import type { WorkspaceSubPath } from '../shared';
@@ -9,47 +9,70 @@ export const enum RouteLogic {
}
export function useRouterHelper(router: NextRouter) {
return useMemo(
() => ({
jumpToPage: (
workspaceId: string,
pageId: string,
logic: RouteLogic = RouteLogic.PUSH
) => {
return router[logic]({
pathname: `/workspace/[workspaceId]/[pageId]`,
query: {
workspaceId,
pageId,
},
});
},
jumpToPublicWorkspacePage: (
workspaceId: string,
pageId: string,
logic: RouteLogic = RouteLogic.PUSH
) => {
return router[logic]({
pathname: `/public-workspace/[workspaceId]/[pageId]`,
query: {
workspaceId,
pageId,
},
});
},
jumpToSubPath: (
workspaceId: string,
subPath: WorkspaceSubPath,
logic: RouteLogic = RouteLogic.PUSH
): Promise<boolean> => {
return router[logic]({
pathname: `/workspace/[workspaceId]/${subPath}`,
query: {
workspaceId,
},
});
},
}),
const jumpToPage = useCallback(
(
workspaceId: string,
pageId: string,
logic: RouteLogic = RouteLogic.PUSH
) => {
return router[logic]({
pathname: `/workspace/[workspaceId]/[pageId]`,
query: {
workspaceId,
pageId,
},
});
},
[router]
);
const jumpToPublicWorkspacePage = useCallback(
(
workspaceId: string,
pageId: string,
logic: RouteLogic = RouteLogic.PUSH
) => {
return router[logic]({
pathname: `/public-workspace/[workspaceId]/[pageId]`,
query: {
workspaceId,
pageId,
},
});
},
[router]
);
const jumpToSubPath = useCallback(
(
workspaceId: string,
subPath: WorkspaceSubPath,
logic: RouteLogic = RouteLogic.PUSH
): Promise<boolean> => {
return router[logic]({
pathname: `/workspace/[workspaceId]/${subPath}`,
query: {
workspaceId,
},
});
},
[router]
);
const openPage = useCallback(
(workspaceId: string, pageId: string) => {
const isPublicWorkspace =
router.pathname.split('/')[1] === 'public-workspace';
if (isPublicWorkspace) {
return jumpToPublicWorkspacePage(workspaceId, pageId);
} else {
return jumpToPage(workspaceId, pageId);
}
},
[jumpToPage, jumpToPublicWorkspacePage, router.pathname]
);
return {
jumpToPage,
jumpToPublicWorkspacePage,
jumpToSubPath,
openPage,
};
}