mirror of
https://github.com/lobehub/lobehub.git
synced 2026-03-26 13:19:34 +07:00
🐛 fix(editor): reset editor state when switching to empty page (#13229)
Fixes LOBE-6321
This commit is contained in:
@@ -4,6 +4,8 @@ import { type IEditor } from '@lobehub/editor';
|
||||
import { memo, useCallback, useEffect, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { EMPTY_EDITOR_STATE } from '@/libs/editor/constants';
|
||||
|
||||
import { type EditorCanvasProps } from './EditorCanvas';
|
||||
import InternalEditor from './InternalEditor';
|
||||
|
||||
@@ -29,6 +31,9 @@ const loadEditorContent = (
|
||||
} else if (editorData.content?.trim()) {
|
||||
editorInstance.setDocument('markdown', editorData.content, { keepId: true });
|
||||
return true;
|
||||
} else {
|
||||
editorInstance.setDocument('json', JSON.stringify(EMPTY_EDITOR_STATE));
|
||||
return true;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[loadEditorContent] Error loading content:', err);
|
||||
|
||||
@@ -7,10 +7,10 @@ import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { createChatInputRichPlugins } from '@/features/ChatInput/InputEditor/plugins';
|
||||
import { EMPTY_EDITOR_STATE } from '@/libs/editor/constants';
|
||||
import { useAgentStore } from '@/store/agent';
|
||||
import { agentSelectors } from '@/store/agent/selectors';
|
||||
|
||||
import { EMPTY_EDITOR_STATE } from '../constants';
|
||||
import { useMentionOptions } from '../ProfileEditor/MentionList';
|
||||
import { useProfileStore } from '../store';
|
||||
import TypoBar from './TypoBar';
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
/**
|
||||
* Empty editor state for initializing the editor
|
||||
* This is the minimal JSON structure required by the editor
|
||||
* Must have at least one paragraph with an empty text node
|
||||
*/
|
||||
export const EMPTY_EDITOR_STATE = {
|
||||
root: {
|
||||
children: [
|
||||
{
|
||||
children: [
|
||||
{
|
||||
detail: 0,
|
||||
format: 0,
|
||||
mode: 'normal',
|
||||
style: '',
|
||||
text: '',
|
||||
type: 'text',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
textFormat: 0,
|
||||
textStyle: '',
|
||||
type: 'paragraph',
|
||||
version: 1,
|
||||
},
|
||||
],
|
||||
direction: null,
|
||||
format: '',
|
||||
indent: 0,
|
||||
type: 'root',
|
||||
version: 1,
|
||||
},
|
||||
};
|
||||
@@ -1,6 +1,8 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { EMPTY_EDITOR_STATE } from '@/libs/editor/constants';
|
||||
|
||||
import { useDocumentStore } from '../../store';
|
||||
|
||||
// Mock services
|
||||
@@ -180,10 +182,23 @@ describe('DocumentStore - Editor Actions', () => {
|
||||
expect(mockEditor.setDocument).toHaveBeenCalledWith('json', JSON.stringify(editorData));
|
||||
});
|
||||
|
||||
it('should not call setDocument when content is empty to avoid editor error', () => {
|
||||
it('should reset editor content when target document is empty', () => {
|
||||
const { result } = renderHook(() => useDocumentStore());
|
||||
const mockEditor = createMockEditor() as any;
|
||||
|
||||
act(() => {
|
||||
result.current.initDocumentWithEditor({
|
||||
content: '# Previous Content',
|
||||
documentId: 'doc-previous',
|
||||
editor: mockEditor,
|
||||
sourceType: 'page',
|
||||
});
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.onEditorInit(mockEditor);
|
||||
});
|
||||
|
||||
act(() => {
|
||||
result.current.initDocumentWithEditor({
|
||||
documentId: 'doc-1',
|
||||
@@ -196,9 +211,10 @@ describe('DocumentStore - Editor Actions', () => {
|
||||
result.current.onEditorInit(mockEditor);
|
||||
});
|
||||
|
||||
// setDocument should NOT be called for empty content
|
||||
// This prevents "setEditorState: the editor state is empty" error
|
||||
expect(mockEditor.setDocument).not.toHaveBeenCalled();
|
||||
expect(mockEditor.setDocument).toHaveBeenLastCalledWith(
|
||||
'json',
|
||||
JSON.stringify(EMPTY_EDITOR_STATE),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { IEditor } from '@lobehub/editor/es/types';
|
||||
import type { EditorState as LobehubEditorState } from '@lobehub/editor/react';
|
||||
import isEqual from 'fast-deep-equal';
|
||||
|
||||
import { EMPTY_EDITOR_STATE } from '@/libs/editor/constants';
|
||||
import { documentService } from '@/services/document';
|
||||
import type { StoreSetter } from '@/store/types';
|
||||
import { setNamespace } from '@/utils/storeDebug';
|
||||
@@ -129,14 +130,14 @@ export class EditorActionImpl {
|
||||
}
|
||||
}
|
||||
|
||||
// Load markdown content if available
|
||||
// Skip setDocument for empty content - let editor use its default empty state
|
||||
if (doc.content?.trim()) {
|
||||
try {
|
||||
try {
|
||||
if (doc.content?.trim()) {
|
||||
editor.setDocument('markdown', doc.content);
|
||||
} catch (err) {
|
||||
console.error('[DocumentStore] Failed to load markdown content:', err);
|
||||
} else {
|
||||
editor.setDocument('json', JSON.stringify(EMPTY_EDITOR_STATE));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[DocumentStore] Failed to load markdown content:', err);
|
||||
}
|
||||
|
||||
this.#set({ editor });
|
||||
|
||||
Reference in New Issue
Block a user