feat(core): support block links on Bi-Directional Links (#8169)

Clsoes [AF-1348](https://linear.app/affine-design/issue/AF-1348/修复-bi-directional-links-里面的链接地址)

* Links to the current document should be ignored on `Backlinks`
* Links to the current document should be ignored on `Outgoing links`

https://github.com/user-attachments/assets/dbc43cea-5aca-4c6f-886a-356e3a91c1f1
This commit is contained in:
fundon
2024-09-11 11:08:12 +00:00
parent b7d05d2078
commit b74dd1c92e
10 changed files with 221 additions and 98 deletions
@@ -35,9 +35,8 @@ export interface PageReferenceRendererOptions {
journalHelper: ReturnType<typeof useJournalHelper>;
t: ReturnType<typeof useI18n>;
docMode?: DocMode;
// linking doc with block or element
blockIds?: string[];
elementIds?: string[];
// Link to block or element
linkToNode?: boolean;
}
// use a function to be rendered in the lit renderer
export function pageReferenceRenderer({
@@ -46,8 +45,7 @@ export function pageReferenceRenderer({
journalHelper,
t,
docMode,
blockIds,
elementIds,
linkToNode = false,
}: PageReferenceRendererOptions) {
const { isPageJournal, getLocalizedJournalDateString } = journalHelper;
const referencedPage = pageMetaHelper.getDocMeta(pageId);
@@ -62,7 +60,7 @@ export function pageReferenceRenderer({
} else {
Icon = LinkedPageIcon;
}
if (blockIds?.length || elementIds?.length) {
if (linkToNode) {
Icon = BlockLinkIcon;
}
}
@@ -89,33 +87,33 @@ export function AffinePageReference({
docCollection,
wrapper: Wrapper,
mode = 'page',
params = {},
params,
}: {
pageId: string;
docCollection: DocCollection;
wrapper?: React.ComponentType<PropsWithChildren>;
mode?: DocMode;
params?: {
mode?: DocMode;
blockIds?: string[];
elementIds?: string[];
};
params?: URLSearchParams;
}) {
const pageMetaHelper = useDocMetaHelper(docCollection);
const journalHelper = useJournalHelper(docCollection);
const t = useI18n();
const { mode: linkedWithMode, blockIds, elementIds } = params;
let linkWithMode: DocMode | null = null;
let linkToNode = false;
if (params) {
linkWithMode = params.get('mode') as DocMode;
linkToNode = params.has('blockIds') || params.has('elementIds');
}
const el = pageReferenceRenderer({
docMode: linkedWithMode ?? mode,
docMode: linkWithMode ?? mode,
pageId,
pageMetaHelper,
journalHelper,
docCollection,
t,
blockIds,
elementIds,
linkToNode,
});
const ref = useRef<HTMLAnchorElement>(null);
@@ -154,20 +152,11 @@ export function AffinePageReference({
const query = useMemo(() => {
// A block/element reference link
const search = new URLSearchParams();
if (linkedWithMode) {
search.set('mode', linkedWithMode);
}
if (blockIds?.length) {
search.set('blockIds', blockIds.join(','));
}
if (elementIds?.length) {
search.set('elementIds', elementIds.join(','));
}
search.set('refreshKey', refreshKey);
return search.size > 0 ? `?${search.toString()}` : '';
}, [blockIds, elementIds, linkedWithMode, refreshKey]);
let str = params?.toString() ?? '';
if (str.length) str += '&';
str += `refreshKey=${refreshKey}`;
return '?' + str;
}, [params, refreshKey]);
return (
<WorkbenchLink
@@ -63,10 +63,14 @@ export const BiDirectionalLinkPanel = () => {
{t['com.affine.page-properties.outgoing-links']()} ·{' '}
{links.length}
</div>
{links.map(link => (
<div key={link.docId} className={styles.link}>
{links.map((link, i) => (
<div
key={`${link.docId}-${link.params?.toString()}-${i}`}
className={styles.link}
>
<AffinePageReference
pageId={link.docId}
params={link.params}
docCollection={workspaceService.workspace.docCollection}
/>
</div>
@@ -7,6 +7,7 @@ import { useJournalInfoHelper } from '@affine/core/hooks/use-journal';
import { EditorService } from '@affine/core/modules/editor';
import { EditorSettingService } from '@affine/core/modules/editor-settting';
import { PeekViewService } from '@affine/core/modules/peek-view';
import { toURLSearchParams } from '@affine/core/utils';
import type { DocMode } from '@blocksuite/blocks';
import { DocTitle, EdgelessEditor, PageEditor } from '@blocksuite/presets';
import type { Doc } from '@blocksuite/store';
@@ -90,12 +91,14 @@ const usePatchSpecs = (page: Doc, shared: boolean, mode: DocMode) => {
const pageId = data.pageId;
if (!pageId) return <span />;
const params = toURLSearchParams(data.params);
return (
<AffinePageReference
docCollection={page.collection}
pageId={pageId}
mode={mode}
params={data.params}
params={params}
/>
);
};