fix: cross-chat data corruption and tiptap editor access errors (#20266)

* fix: prevent cross-chat corruption and editor access errors

* fix: safety check in Messages.svelte and cleanup in RichTextInput
This commit is contained in:
G30
2025-12-31 17:40:35 +04:00
committed by GitHub
parent 5a556b00c3
commit 252a983091
2 changed files with 34 additions and 7 deletions
+4
View File
@@ -346,6 +346,10 @@
}; };
const saveMessage = async (messageId, message) => { const saveMessage = async (messageId, message) => {
if (!history.messages?.[messageId]) {
return;
}
history.messages[messageId] = message; history.messages[messageId] = message;
await updateChat(); await updateChat();
}; };
+30 -7
View File
@@ -416,7 +416,7 @@
}; };
export const setText = (text: string) => { export const setText = (text: string) => {
if (!editor) return; if (!editor || !editor.view) return;
text = text.replaceAll('\n\n', '\n'); text = text.replaceAll('\n\n', '\n');
// reset the editor content // reset the editor content
@@ -448,11 +448,13 @@
} }
selectNextTemplate(editor.view.state, editor.view.dispatch); selectNextTemplate(editor.view.state, editor.view.dispatch);
// Ensure the editor is still valid before trying to focus
focus(); focus();
}; };
export const insertContent = (content) => { export const insertContent = (content) => {
if (!editor) return; if (!editor || !editor.view) return;
const { state, view } = editor; const { state, view } = editor;
const { schema, tr } = state; const { schema, tr } = state;
@@ -466,7 +468,7 @@
}; };
export const replaceVariables = (variables) => { export const replaceVariables = (variables) => {
if (!editor) return; if (!editor || !editor.view) return;
const { state, view } = editor; const { state, view } = editor;
const { doc } = state; const { doc } = state;
@@ -509,11 +511,16 @@
}; };
export const focus = () => { export const focus = () => {
if (editor) { if (editor && editor.view) {
// Check if the editor is destroyed
if (editor.isDestroyed) {
return;
}
try { try {
editor.view?.focus(); editor.view.focus();
// Scroll to the current selection // Scroll to the current selection
editor.view?.dispatch(editor.view.state.tr.scrollIntoView()); editor.view.dispatch(editor.view.state.tr.scrollIntoView());
} catch (e) { } catch (e) {
// sometimes focusing throws an error, ignore // sometimes focusing throws an error, ignore
console.warn('Error focusing editor', e); console.warn('Error focusing editor', e);
@@ -743,7 +750,7 @@
}) })
] ]
: []), : []),
...(richText && showFormattingToolbar ...(richText && showFormattingToolbar
? [ ? [
BubbleMenu.configure({ BubbleMenu.configure({
element: bubbleMenuElement, element: bubbleMenuElement,
@@ -753,6 +760,14 @@
placement: 'top', placement: 'top',
theme: 'transparent', theme: 'transparent',
offset: [0, 2] offset: [0, 2]
},
shouldShow: ({ editor, view, state, oldState, from, to }) => {
// safety check
if (!editor || !editor.view || editor.isDestroyed) {
return false;
}
// default logic
return from !== to;
} }
}), }),
FloatingMenu.configure({ FloatingMenu.configure({
@@ -763,6 +778,14 @@
placement: floatingMenuPlacement, placement: floatingMenuPlacement,
theme: 'transparent', theme: 'transparent',
offset: [-12, 4] offset: [-12, 4]
},
shouldShow: ({ editor, view, state, oldState }) => {
// safety check
if (!editor || !editor.view || editor.isDestroyed) {
return false;
}
// default logic
return editor.isActive('paragraph');
} }
}) })
] ]