feat(workspace): links to single bullets
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m8s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m8s
- copy a link to a bullet from its action bubble or pick a bullet in the link dialog; [[Note#^id|Note › excerpt]] opens the note, jumps to and highlights the bullet, or says it is gone - wiki links render inline with their label and are clickable; the duplicate chip below the text is gone test(e2e): run each suite with its own container, image tag and port, so parallel runs from another working copy no longer remove our server Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d408e7d307
commit
1a49e6b304
12 files changed
+284
-45
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import React, { useState, useEffect, useRef, useCallback, useMemo, useSyncExternalStore } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
import { buildBlockLink } from '../../lib/wikiLink';
|
||||
import {
|
||||
Pin,
|
||||
Users,
|
||||
@@ -51,7 +52,7 @@ export interface DocumentEditorProps {
|
||||
onRestoreDoc?: (docId: string) => void;
|
||||
onOpenShareModal: (doc: Document) => void;
|
||||
onSelectTag: (tag: string) => void;
|
||||
onWikiLinkClick?: (pageTitle: string) => void;
|
||||
onWikiLinkClick?: (pageTitle: string, blockId?: string) => void;
|
||||
onOpenDocBlock?: (docId: string, blockId?: string) => void;
|
||||
onBackMobile?: () => void;
|
||||
onOpenTask?: (taskId: string) => void;
|
||||
@@ -495,6 +496,34 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
}, actions.length ? 8000 : 3500);
|
||||
}, []);
|
||||
|
||||
// Link to a single bullet: [[Titel#^id|Titel › Auszug]] into the clipboard
|
||||
const handleCopyBlockLink = useCallback(
|
||||
(blockId: string) => {
|
||||
const block = blocks.find((b) => b.id === blockId);
|
||||
const link = buildBlockLink(title || doc?.title || 'Notiz', blockId, block?.content || '');
|
||||
const done = () => showNotice('Link zum Punkt kopiert – mit Strg+V in eine Notiz einfügen');
|
||||
if (navigator.clipboard?.writeText) {
|
||||
navigator.clipboard.writeText(link).then(done, () => showNotice(`Kopieren nicht möglich: ${link}`));
|
||||
} else {
|
||||
showNotice(`Kopieren nicht möglich: ${link}`);
|
||||
}
|
||||
},
|
||||
[blocks, title, doc?.title, showNotice]
|
||||
);
|
||||
|
||||
// A link pointed to a bullet that is gone (moved, extracted, deleted): the note opens with a hint
|
||||
const blocksForTargetRef = useRef(blocks);
|
||||
blocksForTargetRef.current = blocks;
|
||||
useEffect(() => {
|
||||
if (!initialFocusedBlockId || !doc?.id) return;
|
||||
const timer = window.setTimeout(() => {
|
||||
if (!blocksForTargetRef.current.some((b) => b.id === initialFocusedBlockId)) {
|
||||
showNotice('Der verlinkte Punkt ist in dieser Notiz nicht mehr vorhanden');
|
||||
}
|
||||
}, 1500);
|
||||
return () => window.clearTimeout(timer);
|
||||
}, [initialFocusedBlockId, doc?.id, showNotice]);
|
||||
|
||||
// The last extraction, so undoing it (toast or Strg+Z) also puts the new note into the trash
|
||||
const lastExtractRef = useRef<{ newDocId: string; blockId: string; link: string } | null>(null);
|
||||
const finishUndoExtract = useCallback(() => {
|
||||
@@ -1188,6 +1217,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
onOpenTask={onOpenTask}
|
||||
onTagClick={onSelectTag}
|
||||
onWikiLinkClick={onWikiLinkClick}
|
||||
onCopyBlockLink={handleCopyBlockLink}
|
||||
initialFocusedBlockId={initialFocusedBlockId}
|
||||
onFocusedBlockChange={(id) => engineRef.current?.focusBlock(id)}
|
||||
lockedBlocks={lockedBlocks}
|
||||
@@ -1277,6 +1307,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
|
||||
onOpenTask={onOpenTask}
|
||||
onTagClick={onSelectTag}
|
||||
onWikiLinkClick={onWikiLinkClick}
|
||||
onCopyBlockLink={handleCopyBlockLink}
|
||||
initialFocusedBlockId={initialFocusedBlockId}
|
||||
onFocusedBlockChange={(id) => engineRef.current?.focusBlock(id)}
|
||||
lockedBlocks={lockedBlocks}
|
||||
|
||||
Reference in new issue
Block a user