🐛(frontend) paste content with comments from another document

When pasting comments, the data-bn-thread-id
attribute is present in the clipboard data.
This indicates that the pasted content contains comments.
But if the content with comments comes from another
document, it will create orphaned comments that
are not linked to this document and create errors.
To avoid this, we refresh the threads to ensure
that only comments relevant to the current document
are displayed.
This commit is contained in:
Anthony LC
2025-12-12 14:45:04 +01:00
parent 08fb191e6b
commit 31bd475418
4 changed files with 85 additions and 8 deletions

View File

@@ -162,6 +162,26 @@ export const BlockNoteEditor = ({ doc, provider }: BlockNoteEditorProps) => {
multi_column:
multiColumnLocales?.[lang as keyof typeof multiColumnLocales],
},
pasteHandler: ({ event, defaultPasteHandler }) => {
// Get clipboard data
const blocknoteData = event.clipboardData?.getData('blocknote/html');
/**
* When pasting comments, the data-bn-thread-id
* attribute is present in the clipboard data.
* This indicates that the pasted content contains comments.
* But if the content with comments comes from another document,
* it will create orphaned comments that are not linked to this document
* and create errors.
* To avoid this, we refresh the threads to ensure that only comments
* relevant to the current document are displayed.
*/
if (blocknoteData && blocknoteData.includes('data-bn-thread-id')) {
void threadStore.refreshThreads();
}
return defaultPasteHandler();
},
resolveUsers: async (userIds) => {
return Promise.resolve(
userIds.map((encodedURIUserId) => {

View File

@@ -117,7 +117,7 @@ export const cssComments = (
}
& svg {
color: var(--c--globals--colors--info-600);
color: var(--c--contextuals--background--semantic--brand--primary);
}
}
@@ -134,15 +134,23 @@ export const cssComments = (
padding-inline: var(--c--globals--spacings--st);
&[data-test='save'] {
border: 1px solid var(--c--globals--colors--info-600);
background: var(--c--globals--colors--info-600);
color: white;
border: 1px solid
var(--c--contextuals--background--semantic--brand--primary);
background: var(
--c--contextuals--background--semantic--brand--primary
);
color: var(
--c--contextuals--content--semantic--brand--on-brand
);
}
&[data-test='cancel'] {
background: white;
border: 1px solid var(--c--globals--colors--gray-300);
color: var(--c--globals--colors--info-600);
border: 1px solid
var(--c--contextuals--border--surface--primary);
color: var(
--c--contextuals--background--semantic--brand--primary
);
}
}
}
@@ -184,7 +192,9 @@ export const cssComments = (
button {
font-size: 0;
background: var(--c--globals--colors--info-600);
background: var(
--c--contextuals--background--semantic--brand--primary
);
width: var(--c--globals--spacings--md);
height: var(--c--globals--spacings--md);
padding: var(--c--globals--spacings--0);
@@ -197,7 +207,7 @@ export const cssComments = (
content: 'arrow_upward_alt';
font-family: 'Material Symbols Outlined Variable', sans-serif;
font-size: 18px;
color: var(--c--globals--colors--gray-100);
color: var(--c--contextuals--content--semantic--brand--on-brand);
}
}
}